ccjk 14.2.2 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +58 -341
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/detect.js +15 -0
- package/dist/commands/detect.js.map +1 -0
- package/dist/commands/doctor.js +68 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/git-install.js +50 -0
- package/dist/commands/git-install.js.map +1 -0
- package/dist/commands/init.js +102 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.js +66 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/menu.js +33 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/core/detect.js +24 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/lint.js +49 -0
- package/dist/core/lint.js.map +1 -0
- package/dist/core/mcp.js +41 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/paths.js +9 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/providers.js +53 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/settings.js +31 -0
- package/dist/core/settings.js.map +1 -0
- package/dist/core/slash-templates.js +56 -0
- package/dist/core/slash-templates.js.map +1 -0
- package/dist/core/tools.js +27 -0
- package/dist/core/tools.js.map +1 -0
- package/package.json +43 -164
- package/README.HONEST.md +0 -176
- package/README.en.md +0 -67
- package/README.ja.md +0 -67
- package/README.ko.md +0 -67
- package/README.zh-CN.md +0 -86
- package/bin/ccjk.mjs +0 -5
- package/bin/ccjk.ts +0 -222
- package/dist/chunks/agent-teams.mjs +0 -145
- package/dist/chunks/agent.mjs +0 -1439
- package/dist/chunks/agents.mjs +0 -3783
- package/dist/chunks/api-cli.mjs +0 -135
- package/dist/chunks/api-config-selector.mjs +0 -159
- package/dist/chunks/api-providers.mjs +0 -144
- package/dist/chunks/api.mjs +0 -115
- package/dist/chunks/auto-bootstrap.mjs +0 -358
- package/dist/chunks/auto-fixer.mjs +0 -95
- package/dist/chunks/auto-updater.mjs +0 -507
- package/dist/chunks/banner.mjs +0 -173
- package/dist/chunks/bash.mjs +0 -187
- package/dist/chunks/boost.mjs +0 -474
- package/dist/chunks/brain-config.mjs +0 -75
- package/dist/chunks/brain-status.mjs +0 -89
- package/dist/chunks/ccjk-agents.mjs +0 -416
- package/dist/chunks/ccjk-all.mjs +0 -1046
- package/dist/chunks/ccjk-config.mjs +0 -445
- package/dist/chunks/ccjk-hooks.mjs +0 -1074
- package/dist/chunks/ccjk-mcp.mjs +0 -763
- package/dist/chunks/ccjk-setup.mjs +0 -765
- package/dist/chunks/ccjk-skills.mjs +0 -518
- package/dist/chunks/ccr.mjs +0 -109
- package/dist/chunks/ccu.mjs +0 -40
- package/dist/chunks/check-updates.mjs +0 -117
- package/dist/chunks/claude-code-incremental-manager.mjs +0 -761
- package/dist/chunks/claude-config.mjs +0 -606
- package/dist/chunks/claude-config2.mjs +0 -62
- package/dist/chunks/claude-wrapper.mjs +0 -85
- package/dist/chunks/clavue-config.mjs +0 -1454
- package/dist/chunks/cleanup-migration.mjs +0 -20
- package/dist/chunks/cli-hook.mjs +0 -4096
- package/dist/chunks/cloud-sync.mjs +0 -29
- package/dist/chunks/code-type-resolver.mjs +0 -880
- package/dist/chunks/codex-config-switch.mjs +0 -452
- package/dist/chunks/codex-provider-manager.mjs +0 -238
- package/dist/chunks/codex-uninstaller.mjs +0 -404
- package/dist/chunks/codex.mjs +0 -2141
- package/dist/chunks/commands.mjs +0 -108
- package/dist/chunks/commands2.mjs +0 -421
- package/dist/chunks/commit.mjs +0 -140
- package/dist/chunks/completion.mjs +0 -517
- package/dist/chunks/config-consolidator.mjs +0 -172
- package/dist/chunks/config-switch.mjs +0 -334
- package/dist/chunks/config.mjs +0 -558
- package/dist/chunks/config2.mjs +0 -484
- package/dist/chunks/config3.mjs +0 -486
- package/dist/chunks/constants.mjs +0 -323
- package/dist/chunks/context-opt.mjs +0 -444
- package/dist/chunks/context.mjs +0 -974
- package/dist/chunks/dashboard.mjs +0 -481
- package/dist/chunks/doctor.mjs +0 -1301
- package/dist/chunks/eval.mjs +0 -502
- package/dist/chunks/evolution.mjs +0 -322
- package/dist/chunks/features.mjs +0 -715
- package/dist/chunks/fish.mjs +0 -181
- package/dist/chunks/fs-operations.mjs +0 -180
- package/dist/chunks/health-alerts.mjs +0 -830
- package/dist/chunks/help.mjs +0 -341
- package/dist/chunks/hook-installer.mjs +0 -48
- package/dist/chunks/impact.mjs +0 -651
- package/dist/chunks/index.mjs +0 -23
- package/dist/chunks/index10.mjs +0 -19
- package/dist/chunks/index11.mjs +0 -1171
- package/dist/chunks/index12.mjs +0 -218
- package/dist/chunks/index13.mjs +0 -679
- package/dist/chunks/index14.mjs +0 -1009
- package/dist/chunks/index15.mjs +0 -194
- package/dist/chunks/index2.mjs +0 -7637
- package/dist/chunks/index3.mjs +0 -171
- package/dist/chunks/index4.mjs +0 -26
- package/dist/chunks/index5.mjs +0 -19
- package/dist/chunks/index6.mjs +0 -19092
- package/dist/chunks/index7.mjs +0 -616
- package/dist/chunks/index8.mjs +0 -1602
- package/dist/chunks/index9.mjs +0 -5384
- package/dist/chunks/init.mjs +0 -1911
- package/dist/chunks/installer.mjs +0 -757
- package/dist/chunks/installer2.mjs +0 -103
- package/dist/chunks/interview.mjs +0 -2927
- package/dist/chunks/json-config.mjs +0 -60
- package/dist/chunks/linux.mjs +0 -3863
- package/dist/chunks/macos.mjs +0 -69
- package/dist/chunks/main.mjs +0 -635
- package/dist/chunks/manager.mjs +0 -1048
- package/dist/chunks/marketplace.mjs +0 -265
- package/dist/chunks/mcp-cli.mjs +0 -205
- package/dist/chunks/mcp-performance.mjs +0 -187
- package/dist/chunks/mcp.mjs +0 -667
- package/dist/chunks/memory-check.mjs +0 -2973
- package/dist/chunks/memory-paths.mjs +0 -259
- package/dist/chunks/memory-sync.mjs +0 -209
- package/dist/chunks/memory.mjs +0 -354
- package/dist/chunks/metrics-display.mjs +0 -153
- package/dist/chunks/monitor.mjs +0 -1856
- package/dist/chunks/notification.mjs +0 -1864
- package/dist/chunks/onboarding.mjs +0 -386
- package/dist/chunks/package.mjs +0 -3
- package/dist/chunks/paradigm.mjs +0 -74
- package/dist/chunks/permission-manager.mjs +0 -250
- package/dist/chunks/permissions.mjs +0 -265
- package/dist/chunks/persistence-manager.mjs +0 -801
- package/dist/chunks/persistence.mjs +0 -707
- package/dist/chunks/platform.mjs +0 -395
- package/dist/chunks/plugin.mjs +0 -1936
- package/dist/chunks/powershell.mjs +0 -213
- package/dist/chunks/prompts.mjs +0 -244
- package/dist/chunks/providers.mjs +0 -263
- package/dist/chunks/quick-actions.mjs +0 -335
- package/dist/chunks/quick-provider.mjs +0 -755
- package/dist/chunks/quick-setup.mjs +0 -421
- package/dist/chunks/remote.mjs +0 -497
- package/dist/chunks/research.mjs +0 -1904
- package/dist/chunks/rollback.mjs +0 -38
- package/dist/chunks/session-manager.mjs +0 -1371
- package/dist/chunks/session.mjs +0 -878
- package/dist/chunks/sessions.mjs +0 -106
- package/dist/chunks/silent-updater.mjs +0 -396
- package/dist/chunks/simple-config.mjs +0 -122
- package/dist/chunks/skill.mjs +0 -117
- package/dist/chunks/skill2.mjs +0 -9052
- package/dist/chunks/skills-sync.mjs +0 -1343
- package/dist/chunks/skills.mjs +0 -577
- package/dist/chunks/slash-commands.mjs +0 -208
- package/dist/chunks/smart-guide.mjs +0 -247
- package/dist/chunks/snapshot.mjs +0 -58
- package/dist/chunks/startup.mjs +0 -487
- package/dist/chunks/stats.mjs +0 -191
- package/dist/chunks/status.mjs +0 -471
- package/dist/chunks/team.mjs +0 -63
- package/dist/chunks/thinking.mjs +0 -626
- package/dist/chunks/trace.mjs +0 -57
- package/dist/chunks/uninstall.mjs +0 -852
- package/dist/chunks/update.mjs +0 -174
- package/dist/chunks/upgrade-manager.mjs +0 -204
- package/dist/chunks/upgrade.mjs +0 -133
- package/dist/chunks/version-checker.mjs +0 -891
- package/dist/chunks/vim.mjs +0 -903
- package/dist/chunks/windows.mjs +0 -14
- package/dist/chunks/workflows.mjs +0 -633
- package/dist/chunks/wsl.mjs +0 -129
- package/dist/chunks/zero-config.mjs +0 -871
- package/dist/chunks/zsh.mjs +0 -182
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -2684
- package/dist/i18n/locales/en/agent-teams.json +0 -18
- package/dist/i18n/locales/en/agentBrowser.json +0 -80
- package/dist/i18n/locales/en/agents.json +0 -135
- package/dist/i18n/locales/en/api.json +0 -63
- package/dist/i18n/locales/en/ccjk-agents.json +0 -33
- package/dist/i18n/locales/en/ccjk-all.json +0 -23
- package/dist/i18n/locales/en/ccjk-skills.json +0 -22
- package/dist/i18n/locales/en/ccjk.json +0 -276
- package/dist/i18n/locales/en/ccr.json +0 -65
- package/dist/i18n/locales/en/claude-md.json +0 -73
- package/dist/i18n/locales/en/cli.json +0 -148
- package/dist/i18n/locales/en/cloud-setup.json +0 -31
- package/dist/i18n/locales/en/cloud-sync.json +0 -147
- package/dist/i18n/locales/en/cloud.json +0 -40
- package/dist/i18n/locales/en/cloudPlugins.json +0 -118
- package/dist/i18n/locales/en/codex.json +0 -184
- package/dist/i18n/locales/en/cometix.json +0 -29
- package/dist/i18n/locales/en/common.json +0 -68
- package/dist/i18n/locales/en/config.json +0 -108
- package/dist/i18n/locales/en/configuration.json +0 -236
- package/dist/i18n/locales/en/context.json +0 -85
- package/dist/i18n/locales/en/dashboard.json +0 -78
- package/dist/i18n/locales/en/errors.json +0 -26
- package/dist/i18n/locales/en/evolution.json +0 -54
- package/dist/i18n/locales/en/hooks.json +0 -74
- package/dist/i18n/locales/en/hooksSync.json +0 -133
- package/dist/i18n/locales/en/installation.json +0 -83
- package/dist/i18n/locales/en/interview.json +0 -104
- package/dist/i18n/locales/en/language.json +0 -19
- package/dist/i18n/locales/en/lsp.json +0 -78
- package/dist/i18n/locales/en/marketplace.json +0 -116
- package/dist/i18n/locales/en/mcp.json +0 -180
- package/dist/i18n/locales/en/memory.json +0 -23
- package/dist/i18n/locales/en/menu.json +0 -299
- package/dist/i18n/locales/en/multi-config.json +0 -79
- package/dist/i18n/locales/en/notification.json +0 -307
- package/dist/i18n/locales/en/permissions.json +0 -95
- package/dist/i18n/locales/en/persistence.json +0 -127
- package/dist/i18n/locales/en/plugins.json +0 -146
- package/dist/i18n/locales/en/quick-actions.json +0 -78
- package/dist/i18n/locales/en/registry.json +0 -54
- package/dist/i18n/locales/en/remote.json +0 -93
- package/dist/i18n/locales/en/sandbox.json +0 -44
- package/dist/i18n/locales/en/setup.json +0 -44
- package/dist/i18n/locales/en/shencha.json +0 -14
- package/dist/i18n/locales/en/skills.json +0 -100
- package/dist/i18n/locales/en/skillsSync.json +0 -74
- package/dist/i18n/locales/en/smartGuide.json +0 -49
- package/dist/i18n/locales/en/stats.json +0 -20
- package/dist/i18n/locales/en/subagent.json +0 -69
- package/dist/i18n/locales/en/superpowers.json +0 -117
- package/dist/i18n/locales/en/team.json +0 -7
- package/dist/i18n/locales/en/thinking.json +0 -65
- package/dist/i18n/locales/en/tools.json +0 -42
- package/dist/i18n/locales/en/uninstall.json +0 -56
- package/dist/i18n/locales/en/updater.json +0 -29
- package/dist/i18n/locales/en/vim.json +0 -169
- package/dist/i18n/locales/en/workflow.json +0 -55
- package/dist/i18n/locales/en/workspace.json +0 -108
- package/dist/i18n/locales/zh-CN/agent-teams.json +0 -18
- package/dist/i18n/locales/zh-CN/agentBrowser.json +0 -80
- package/dist/i18n/locales/zh-CN/agents.json +0 -135
- package/dist/i18n/locales/zh-CN/api.json +0 -63
- package/dist/i18n/locales/zh-CN/ccjk-agents.json +0 -33
- package/dist/i18n/locales/zh-CN/ccjk-all.json +0 -23
- package/dist/i18n/locales/zh-CN/ccjk-skills.json +0 -22
- package/dist/i18n/locales/zh-CN/ccjk.json +0 -276
- package/dist/i18n/locales/zh-CN/ccr.json +0 -65
- package/dist/i18n/locales/zh-CN/claude-md.json +0 -73
- package/dist/i18n/locales/zh-CN/cli.json +0 -148
- package/dist/i18n/locales/zh-CN/cloud-setup.json +0 -31
- package/dist/i18n/locales/zh-CN/cloud-sync.json +0 -147
- package/dist/i18n/locales/zh-CN/cloud.json +0 -40
- package/dist/i18n/locales/zh-CN/cloudPlugins.json +0 -118
- package/dist/i18n/locales/zh-CN/codex.json +0 -184
- package/dist/i18n/locales/zh-CN/cometix.json +0 -29
- package/dist/i18n/locales/zh-CN/common.json +0 -68
- package/dist/i18n/locales/zh-CN/config.json +0 -108
- package/dist/i18n/locales/zh-CN/configuration.json +0 -234
- package/dist/i18n/locales/zh-CN/context.json +0 -85
- package/dist/i18n/locales/zh-CN/dashboard.json +0 -78
- package/dist/i18n/locales/zh-CN/errors.json +0 -26
- package/dist/i18n/locales/zh-CN/evolution.json +0 -54
- package/dist/i18n/locales/zh-CN/hooks.json +0 -74
- package/dist/i18n/locales/zh-CN/hooksSync.json +0 -133
- package/dist/i18n/locales/zh-CN/installation.json +0 -83
- package/dist/i18n/locales/zh-CN/interview.json +0 -104
- package/dist/i18n/locales/zh-CN/language.json +0 -19
- package/dist/i18n/locales/zh-CN/lsp.json +0 -78
- package/dist/i18n/locales/zh-CN/marketplace.json +0 -116
- package/dist/i18n/locales/zh-CN/mcp.json +0 -180
- package/dist/i18n/locales/zh-CN/memory.json +0 -23
- package/dist/i18n/locales/zh-CN/menu.json +0 -299
- package/dist/i18n/locales/zh-CN/multi-config.json +0 -79
- package/dist/i18n/locales/zh-CN/notification.json +0 -307
- package/dist/i18n/locales/zh-CN/permissions.json +0 -95
- package/dist/i18n/locales/zh-CN/persistence.json +0 -127
- package/dist/i18n/locales/zh-CN/plugins.json +0 -146
- package/dist/i18n/locales/zh-CN/quick-actions.json +0 -78
- package/dist/i18n/locales/zh-CN/registry.json +0 -54
- package/dist/i18n/locales/zh-CN/remote.json +0 -93
- package/dist/i18n/locales/zh-CN/sandbox.json +0 -44
- package/dist/i18n/locales/zh-CN/setup.json +0 -44
- package/dist/i18n/locales/zh-CN/shencha.json +0 -14
- package/dist/i18n/locales/zh-CN/skills.json +0 -100
- package/dist/i18n/locales/zh-CN/skillsSync.json +0 -74
- package/dist/i18n/locales/zh-CN/smartGuide.json +0 -49
- package/dist/i18n/locales/zh-CN/stats.json +0 -20
- package/dist/i18n/locales/zh-CN/subagent.json +0 -69
- package/dist/i18n/locales/zh-CN/superpowers.json +0 -117
- package/dist/i18n/locales/zh-CN/team.json +0 -7
- package/dist/i18n/locales/zh-CN/thinking.json +0 -65
- package/dist/i18n/locales/zh-CN/tools.json +0 -42
- package/dist/i18n/locales/zh-CN/uninstall.json +0 -56
- package/dist/i18n/locales/zh-CN/updater.json +0 -29
- package/dist/i18n/locales/zh-CN/vim.json +0 -169
- package/dist/i18n/locales/zh-CN/workflow.json +0 -55
- package/dist/i18n/locales/zh-CN/workspace.json +0 -108
- package/dist/index.d.mts +0 -5658
- package/dist/index.d.ts +0 -5658
- package/dist/index.mjs +0 -3732
- package/dist/shared/ccjk.5bEolFrk.mjs +0 -254
- package/dist/shared/ccjk.8oaxX4iR.mjs +0 -90
- package/dist/shared/ccjk.B2U7DsPy.mjs +0 -31
- package/dist/shared/ccjk.B2f-cwUP.mjs +0 -468
- package/dist/shared/ccjk.BAGoDD49.mjs +0 -36
- package/dist/shared/ccjk.BBtCGd_g.mjs +0 -899
- package/dist/shared/ccjk.BFQ7yr5S.mjs +0 -16
- package/dist/shared/ccjk.BLsIiTqO.mjs +0 -449
- package/dist/shared/ccjk.BXv8aYs1.mjs +0 -170
- package/dist/shared/ccjk.BnsY5WxD.mjs +0 -171
- package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
- package/dist/shared/ccjk.Bq8TqZG_.mjs +0 -189
- package/dist/shared/ccjk.BtrioX1Z.mjs +0 -25
- package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
- package/dist/shared/ccjk.BzPbSEP2.mjs +0 -115
- package/dist/shared/ccjk.C0WLUnFV.mjs +0 -293
- package/dist/shared/ccjk.C1hANZTu.mjs +0 -19
- package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
- package/dist/shared/ccjk.CNhnT6uQ.mjs +0 -636
- package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
- package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
- package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
- package/dist/shared/ccjk.CoCHVXl3.mjs +0 -3951
- package/dist/shared/ccjk.CwGZSTAK.mjs +0 -319
- package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
- package/dist/shared/ccjk.D-magaEx.mjs +0 -763
- package/dist/shared/ccjk.D0g2ABGg.mjs +0 -171
- package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
- package/dist/shared/ccjk.D75wivnp.mjs +0 -142
- package/dist/shared/ccjk.DDL-4C-k.mjs +0 -100
- package/dist/shared/ccjk.DFRPtmK_.mjs +0 -75
- package/dist/shared/ccjk.DMV3x5Sd.mjs +0 -299
- package/dist/shared/ccjk.DZ2LLOa-.mjs +0 -2195
- package/dist/shared/ccjk.DbigonEQ.mjs +0 -698
- package/dist/shared/ccjk.DcMvE7lf.mjs +0 -618
- package/dist/shared/ccjk.DeWpAShp.mjs +0 -1828
- package/dist/shared/ccjk.DhJ1kyDR.mjs +0 -30
- package/dist/shared/ccjk.DlTXS9rP.mjs +0 -224
- package/dist/shared/ccjk.DopKzo3z.mjs +0 -305
- package/dist/shared/ccjk.DsZsc4LR.mjs +0 -1280
- package/dist/shared/ccjk.DuzJZlgj.mjs +0 -418
- package/dist/shared/ccjk.Dxgd2vjc.mjs +0 -444
- package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
- package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
- package/dist/shared/ccjk.L7yC58_i.mjs +0 -225
- package/dist/shared/ccjk.MwtjAULc.mjs +0 -1447
- package/dist/shared/ccjk.OJKHVSOb.mjs +0 -2005
- package/dist/shared/ccjk.OTnevPNE.mjs +0 -225
- package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
- package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
- package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
- package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
- package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
- package/dist/shared/ccjk.i_vn-9C3.mjs +0 -317
- package/dist/shared/ccjk.lG3ccFjm.mjs +0 -885
- package/dist/shared/ccjk.wLJHO0Af.mjs +0 -244
- package/dist/shared/ccjk.y-a_1vK4.mjs +0 -5127
- package/dist/templates/agents/README.md +0 -78
- package/dist/templates/agents/fullstack-developer.json +0 -70
- package/dist/templates/agents/go-expert.json +0 -69
- package/dist/templates/agents/index.json +0 -64
- package/dist/templates/agents/python-expert.json +0 -69
- package/dist/templates/agents/react-specialist.json +0 -69
- package/dist/templates/agents/testing-automation-expert.json +0 -70
- package/dist/templates/agents/typescript-architect.json +0 -69
- package/dist/templates/claude-code/common/settings.json +0 -109
- package/dist/templates/common/error-prevention.md +0 -267
- package/dist/templates/common/karpathy-baseline.md +0 -83
- package/dist/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
- package/dist/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
- package/dist/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
- package/dist/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
- package/dist/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
- package/dist/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
- package/dist/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
- package/dist/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
- package/dist/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
- package/dist/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
- package/dist/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
- package/dist/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
- package/dist/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
- package/dist/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
- package/dist/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
- package/dist/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
- package/dist/templates/common/workflow/essential/en/feat.md +0 -92
- package/dist/templates/common/workflow/essential/en/goal.md +0 -147
- package/dist/templates/common/workflow/essential/en/init-project.md +0 -53
- package/dist/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
- package/dist/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
- package/dist/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
- package/dist/templates/common/workflow/essential/zh-CN/feat.md +0 -315
- package/dist/templates/common/workflow/essential/zh-CN/goal.md +0 -146
- package/dist/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
- package/dist/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
- package/dist/templates/common/workflow/git/en/git-commit.md +0 -205
- package/dist/templates/common/workflow/git/en/git-rollback.md +0 -90
- package/dist/templates/common/workflow/git/en/git-worktree.md +0 -276
- package/dist/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
- package/dist/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
- package/dist/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
- package/dist/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
- package/dist/templates/common/workflow/interview/en/interview.md +0 -67
- package/dist/templates/common/workflow/interview/zh-CN/interview.md +0 -67
- package/dist/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
- package/dist/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
- package/dist/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
- package/dist/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
- package/dist/templates/common/workflow/sixStep/en/workflow.md +0 -83
- package/dist/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
- package/dist/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
- package/dist/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
- package/dist/templates/hooks/README.md +0 -212
- package/dist/templates/hooks/git-workflow-hooks.md +0 -551
- package/dist/templates/hooks/post-test/coverage.json +0 -21
- package/dist/templates/hooks/post-test/summary.json +0 -21
- package/dist/templates/hooks/post-test-coverage.md +0 -434
- package/dist/templates/hooks/pre-commit/eslint.json +0 -22
- package/dist/templates/hooks/pre-commit/prettier.json +0 -22
- package/dist/templates/hooks/pre-commit-black.md +0 -274
- package/dist/templates/hooks/pre-commit-eslint.md +0 -153
- package/dist/templates/hooks/pre-commit-gofmt.md +0 -284
- package/dist/templates/hooks/pre-commit-prettier.md +0 -212
- package/dist/templates/hooks/pre-commit-type-check.md +0 -377
- package/dist/templates/skills/ccjk-init.md +0 -154
- package/dist/templates/skills/ccjk-mcp-setup.md +0 -205
- package/dist/templates/skills/ccjk-troubleshoot.md +0 -228
- package/dist/templates/skills/django-patterns.md +0 -1016
- package/dist/templates/skills/git-workflow.md +0 -748
- package/dist/templates/skills/go-idioms.md +0 -963
- package/dist/templates/skills/index.json +0 -132
- package/dist/templates/skills/nextjs-optimization.md +0 -694
- package/dist/templates/skills/python-pep8.md +0 -852
- package/dist/templates/skills/react-patterns.md +0 -686
- package/dist/templates/skills/rust-patterns.md +0 -1057
- package/dist/templates/skills/security-best-practices.md +0 -1413
- package/dist/templates/skills/testing-best-practices.md +0 -1315
- package/dist/templates/skills/ts-best-practices.md +0 -354
- package/templates/agents/README.md +0 -78
- package/templates/agents/fullstack-developer.json +0 -70
- package/templates/agents/go-expert.json +0 -69
- package/templates/agents/index.json +0 -64
- package/templates/agents/python-expert.json +0 -69
- package/templates/agents/react-specialist.json +0 -69
- package/templates/agents/testing-automation-expert.json +0 -70
- package/templates/agents/typescript-architect.json +0 -69
- package/templates/claude-code/common/settings.json +0 -109
- package/templates/common/error-prevention.md +0 -267
- package/templates/common/karpathy-baseline.md +0 -83
- package/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
- package/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
- package/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
- package/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
- package/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
- package/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
- package/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
- package/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
- package/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
- package/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
- package/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
- package/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
- package/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
- package/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
- package/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
- package/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
- package/templates/common/workflow/essential/en/feat.md +0 -92
- package/templates/common/workflow/essential/en/goal.md +0 -147
- package/templates/common/workflow/essential/en/init-project.md +0 -53
- package/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
- package/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
- package/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
- package/templates/common/workflow/essential/zh-CN/feat.md +0 -315
- package/templates/common/workflow/essential/zh-CN/goal.md +0 -146
- package/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
- package/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
- package/templates/common/workflow/git/en/git-commit.md +0 -205
- package/templates/common/workflow/git/en/git-rollback.md +0 -90
- package/templates/common/workflow/git/en/git-worktree.md +0 -276
- package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
- package/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
- package/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
- package/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
- package/templates/common/workflow/interview/en/interview.md +0 -67
- package/templates/common/workflow/interview/zh-CN/interview.md +0 -67
- package/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
- package/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
- package/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
- package/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
- package/templates/common/workflow/sixStep/en/workflow.md +0 -83
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
- package/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
- package/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
- package/templates/hooks/README.md +0 -212
- package/templates/hooks/git-workflow-hooks.md +0 -551
- package/templates/hooks/post-test/coverage.json +0 -21
- package/templates/hooks/post-test/summary.json +0 -21
- package/templates/hooks/post-test-coverage.md +0 -434
- package/templates/hooks/pre-commit/eslint.json +0 -22
- package/templates/hooks/pre-commit/prettier.json +0 -22
- package/templates/hooks/pre-commit-black.md +0 -274
- package/templates/hooks/pre-commit-eslint.md +0 -153
- package/templates/hooks/pre-commit-gofmt.md +0 -284
- package/templates/hooks/pre-commit-prettier.md +0 -212
- package/templates/hooks/pre-commit-type-check.md +0 -377
- package/templates/skills/basic.hbs +0 -72
- package/templates/skills/ccjk-init.md +0 -154
- package/templates/skills/ccjk-mcp-setup.md +0 -205
- package/templates/skills/ccjk-troubleshoot.md +0 -228
- package/templates/skills/code-refactor.hbs +0 -133
- package/templates/skills/code-review.hbs +0 -141
- package/templates/skills/django-patterns.md +0 -1016
- package/templates/skills/git-workflow.md +0 -748
- package/templates/skills/go-idioms.md +0 -963
- package/templates/skills/index.json +0 -132
- package/templates/skills/nextjs-optimization.md +0 -694
- package/templates/skills/python-pep8.md +0 -852
- package/templates/skills/react-patterns.md +0 -686
- package/templates/skills/rust-patterns.md +0 -1057
- package/templates/skills/security-best-practices.md +0 -1413
- package/templates/skills/testing-best-practices.md +0 -1315
- package/templates/skills/ts-best-practices.md +0 -354
- package/templates/skills/type-fix.hbs +0 -132
|
@@ -1,1057 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rust-patterns
|
|
3
|
-
description: Rust ownership patterns, borrow checker, lifetime annotations, and async/await
|
|
4
|
-
description_zh: Rust 所有权模式、借用检查器、生命周期注解和 async/await
|
|
5
|
-
version: 1.0.0
|
|
6
|
-
category: programming
|
|
7
|
-
triggers: ['/rust-patterns', '/rust', '/ownership', '/lifetimes', '/async-rust']
|
|
8
|
-
use_when:
|
|
9
|
-
- Writing safe and efficient Rust code with proper ownership
|
|
10
|
-
- Implementing async/await patterns and concurrent programming
|
|
11
|
-
- Working with lifetimes and borrow checker
|
|
12
|
-
- Code review for Rust projects
|
|
13
|
-
use_when_zh:
|
|
14
|
-
- 编写具有适当所有权的安全高效 Rust 代码
|
|
15
|
-
- 实现 async/await 模式和并发编程
|
|
16
|
-
- 使用生命周期和借用检查器
|
|
17
|
-
- Rust 项目代码审查
|
|
18
|
-
auto_activate: true
|
|
19
|
-
priority: 8
|
|
20
|
-
agents: [rust-expert, systems-programmer]
|
|
21
|
-
tags: [rust, ownership, lifetimes, async, safety, performance]
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
# Rust Patterns | Rust 模式
|
|
25
|
-
|
|
26
|
-
## Context | 上下文
|
|
27
|
-
|
|
28
|
-
Use this skill when writing Rust code that leverages ownership, borrowing, and lifetimes for memory safety without garbage collection. Essential for systems programming and high-performance applications.
|
|
29
|
-
|
|
30
|
-
在编写利用所有权、借用和生命周期实现内存安全而无需垃圾回收的 Rust 代码时使用此技能。对于系统编程和高性能应用程序至关重要。
|
|
31
|
-
|
|
32
|
-
## Ownership and Borrowing | 所有权和借用
|
|
33
|
-
|
|
34
|
-
### 1. Ownership Patterns | 所有权模式
|
|
35
|
-
|
|
36
|
-
```rust
|
|
37
|
-
use std::collections::HashMap;
|
|
38
|
-
|
|
39
|
-
// ✅ Good: Clear ownership patterns
|
|
40
|
-
|
|
41
|
-
#[derive(Debug, Clone)]
|
|
42
|
-
pub struct User {
|
|
43
|
-
pub id: u64,
|
|
44
|
-
pub name: String,
|
|
45
|
-
pub email: String,
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
impl User {
|
|
49
|
-
pub fn new(id: u64, name: String, email: String) -> Self {
|
|
50
|
-
Self { id, name, email }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Taking ownership when we need to consume the value
|
|
54
|
-
pub fn into_summary(self) -> String {
|
|
55
|
-
format!("{} ({})", self.name, self.email)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Borrowing immutably when we only need to read
|
|
59
|
-
pub fn display_info(&self) -> String {
|
|
60
|
-
format!("User {}: {} <{}>", self.id, self.name, self.email)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Borrowing mutably when we need to modify
|
|
64
|
-
pub fn update_email(&mut self, new_email: String) -> Result<(), &'static str> {
|
|
65
|
-
if new_email.contains('@') {
|
|
66
|
-
self.email = new_email;
|
|
67
|
-
Ok(())
|
|
68
|
-
} else {
|
|
69
|
-
Err("Invalid email format")
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ✅ Good: Repository pattern with proper ownership
|
|
75
|
-
pub struct UserRepository {
|
|
76
|
-
users: HashMap<u64, User>,
|
|
77
|
-
next_id: u64,
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
impl UserRepository {
|
|
81
|
-
pub fn new() -> Self {
|
|
82
|
-
Self {
|
|
83
|
-
users: HashMap::new(),
|
|
84
|
-
next_id: 1,
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Taking ownership of the user data
|
|
89
|
-
pub fn create_user(&mut self, name: String, email: String) -> u64 {
|
|
90
|
-
let id = self.next_id;
|
|
91
|
-
self.next_id += 1;
|
|
92
|
-
|
|
93
|
-
let user = User::new(id, name, email);
|
|
94
|
-
self.users.insert(id, user);
|
|
95
|
-
|
|
96
|
-
id
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Returning a reference to avoid unnecessary cloning
|
|
100
|
-
pub fn get_user(&self, id: u64) -> Option<&User> {
|
|
101
|
-
self.users.get(&id)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Returning a mutable reference for in-place updates
|
|
105
|
-
pub fn get_user_mut(&mut self, id: u64) -> Option<&mut User> {
|
|
106
|
-
self.users.get_mut(&id)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Taking ownership when removing
|
|
110
|
-
pub fn remove_user(&mut self, id: u64) -> Option<User> {
|
|
111
|
-
self.users.remove(&id)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Returning an iterator over references
|
|
115
|
-
pub fn all_users(&self) -> impl Iterator<Item = &User> {
|
|
116
|
-
self.users.values()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Method that consumes self and returns owned data
|
|
120
|
-
pub fn into_users(self) -> Vec<User> {
|
|
121
|
-
self.users.into_values().collect()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// ✅ Good: Builder pattern with ownership transfer
|
|
126
|
-
pub struct UserBuilder {
|
|
127
|
-
name: Option<String>,
|
|
128
|
-
email: Option<String>,
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
impl UserBuilder {
|
|
132
|
-
pub fn new() -> Self {
|
|
133
|
-
Self {
|
|
134
|
-
name: None,
|
|
135
|
-
email: None,
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Taking ownership of self and returning it (fluent interface)
|
|
140
|
-
pub fn name(mut self, name: String) -> Self {
|
|
141
|
-
self.name = Some(name);
|
|
142
|
-
self
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
pub fn email(mut self, email: String) -> Self {
|
|
146
|
-
self.email = Some(email);
|
|
147
|
-
self
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Consuming self to build the final object
|
|
151
|
-
pub fn build(self, id: u64) -> Result<User, &'static str> {
|
|
152
|
-
let name = self.name.ok_or("Name is required")?;
|
|
153
|
-
let email = self.email.ok_or("Email is required")?;
|
|
154
|
-
|
|
155
|
-
Ok(User::new(id, name, email))
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Usage examples
|
|
160
|
-
fn ownership_examples() {
|
|
161
|
-
let mut repo = UserRepository::new();
|
|
162
|
-
|
|
163
|
-
// Create user - strings are moved into the method
|
|
164
|
-
let user_id = repo.create_user("Alice".to_string(), "alice@example.com".to_string());
|
|
165
|
-
|
|
166
|
-
// Borrow user immutably
|
|
167
|
-
if let Some(user) = repo.get_user(user_id) {
|
|
168
|
-
println!("{}", user.display_info());
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Borrow user mutably
|
|
172
|
-
if let Some(user) = repo.get_user_mut(user_id) {
|
|
173
|
-
let _ = user.update_email("alice.new@example.com".to_string());
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Builder pattern
|
|
177
|
-
let user = UserBuilder::new()
|
|
178
|
-
.name("Bob".to_string())
|
|
179
|
-
.email("bob@example.com".to_string())
|
|
180
|
-
.build(2)
|
|
181
|
-
.expect("Failed to build user");
|
|
182
|
-
|
|
183
|
-
println!("{}", user.into_summary()); // user is consumed here
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// ❌ Bad: Unclear ownership and unnecessary cloning
|
|
187
|
-
fn bad_ownership_example() {
|
|
188
|
-
let user = User::new(1, "Alice".to_string(), "alice@example.com".to_string());
|
|
189
|
-
|
|
190
|
-
// Unnecessary clone
|
|
191
|
-
let user_copy = user.clone();
|
|
192
|
-
println!("{}", user_copy.display_info());
|
|
193
|
-
|
|
194
|
-
// Could have just borrowed
|
|
195
|
-
println!("{}", user.display_info());
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### 2. Smart Pointers | 智能指针
|
|
200
|
-
|
|
201
|
-
```rust
|
|
202
|
-
use std::rc::{Rc, Weak};
|
|
203
|
-
use std::cell::{RefCell, Cell};
|
|
204
|
-
use std::sync::{Arc, Mutex, RwLock};
|
|
205
|
-
use std::thread;
|
|
206
|
-
|
|
207
|
-
// ✅ Good: Using Rc for shared ownership (single-threaded)
|
|
208
|
-
#[derive(Debug)]
|
|
209
|
-
struct Node {
|
|
210
|
-
value: i32,
|
|
211
|
-
children: Vec<Rc<Node>>,
|
|
212
|
-
parent: Option<Weak<Node>>,
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
impl Node {
|
|
216
|
-
fn new(value: i32) -> Rc<Self> {
|
|
217
|
-
Rc::new(Node {
|
|
218
|
-
value,
|
|
219
|
-
children: Vec::new(),
|
|
220
|
-
parent: None,
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
fn add_child(parent: &Rc<Node>, child: Rc<Node>) {
|
|
225
|
-
// This would require RefCell for interior mutability in practice
|
|
226
|
-
// Simplified for demonstration
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// ✅ Good: Using RefCell for interior mutability
|
|
231
|
-
struct Counter {
|
|
232
|
-
value: RefCell<i32>,
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
impl Counter {
|
|
236
|
-
fn new() -> Self {
|
|
237
|
-
Self {
|
|
238
|
-
value: RefCell::new(0),
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
fn increment(&self) {
|
|
243
|
-
let mut value = self.value.borrow_mut();
|
|
244
|
-
*value += 1;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
fn get(&self) -> i32 {
|
|
248
|
-
*self.value.borrow()
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// ✅ Good: Using Arc and Mutex for thread-safe shared state
|
|
253
|
-
#[derive(Clone)]
|
|
254
|
-
struct ThreadSafeCounter {
|
|
255
|
-
value: Arc<Mutex<i32>>,
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
impl ThreadSafeCounter {
|
|
259
|
-
fn new() -> Self {
|
|
260
|
-
Self {
|
|
261
|
-
value: Arc::new(Mutex::new(0)),
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
fn increment(&self) {
|
|
266
|
-
let mut value = self.value.lock().unwrap();
|
|
267
|
-
*value += 1;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
fn get(&self) -> i32 {
|
|
271
|
-
*self.value.lock().unwrap()
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// ✅ Good: Using RwLock for read-heavy workloads
|
|
276
|
-
struct ReadHeavyData {
|
|
277
|
-
data: Arc<RwLock<HashMap<String, String>>>,
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
impl ReadHeavyData {
|
|
281
|
-
fn new() -> Self {
|
|
282
|
-
Self {
|
|
283
|
-
data: Arc::new(RwLock::new(HashMap::new())),
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
fn get(&self, key: &str) -> Option<String> {
|
|
288
|
-
let data = self.data.read().unwrap();
|
|
289
|
-
data.get(key).cloned()
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
fn insert(&self, key: String, value: String) {
|
|
293
|
-
let mut data = self.data.write().unwrap();
|
|
294
|
-
data.insert(key, value);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Usage with threads
|
|
299
|
-
fn smart_pointer_examples() {
|
|
300
|
-
// Single-threaded reference counting
|
|
301
|
-
let counter = Counter::new();
|
|
302
|
-
counter.increment();
|
|
303
|
-
println!("Counter: ", counter.get());
|
|
304
|
-
|
|
305
|
-
// Multi-threaded shared state
|
|
306
|
-
let thread_safe_counter = ThreadSafeCounter::new();
|
|
307
|
-
let mut handles = vec![];
|
|
308
|
-
|
|
309
|
-
for _ in 0..10 {
|
|
310
|
-
let counter = thread_safe_counter.clone();
|
|
311
|
-
let handle = thread::spawn(move || {
|
|
312
|
-
for _ in 0..100 {
|
|
313
|
-
counter.increment();
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
handles.push(handle);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
for handle in handles {
|
|
320
|
-
handle.join().unwrap();
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
println!("Final count: {}", thread_safe_counter.get());
|
|
324
|
-
}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
## Lifetimes and Borrowing | 生命周期和借用
|
|
328
|
-
|
|
329
|
-
### 1. Lifetime Annotations | 生命周期注解
|
|
330
|
-
|
|
331
|
-
```rust
|
|
332
|
-
// ✅ Good: Proper lifetime annotations
|
|
333
|
-
|
|
334
|
-
// Simple lifetime parameter
|
|
335
|
-
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
|
336
|
-
if x.len() > y.len() {
|
|
337
|
-
x
|
|
338
|
-
} else {
|
|
339
|
-
y
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Multiple lifetime parameters
|
|
344
|
-
fn first_word<'a, 'b>(s: &'a str, _delimiter: &'b str) -> &'a str {
|
|
345
|
-
s.split_whitespace().next().unwrap_or("")
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Struct with lifetime parameters
|
|
349
|
-
#[derive(Debug)]
|
|
350
|
-
struct TextProcessor<'a> {
|
|
351
|
-
text: &'a str,
|
|
352
|
-
processed: Vec<&'a str>,
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
impl<'a> TextProcessor<'a> {
|
|
356
|
-
fn new(text: &'a str) -> Self {
|
|
357
|
-
Self {
|
|
358
|
-
text,
|
|
359
|
-
processed: Vec::new(),
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
fn process_words(&mut self) {
|
|
364
|
-
self.processed = self.text
|
|
365
|
-
.split_whitespace()
|
|
366
|
-
.filter(|word| word.len() > 3)
|
|
367
|
-
.collect();
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
fn get_processed(&self) -> &[&'a str] {
|
|
371
|
-
&self.processed
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Method with additional lifetime parameter
|
|
375
|
-
fn find_in_text<'b>(&self, pattern: &'b str) -> Option<&'a str> {
|
|
376
|
-
self.text
|
|
377
|
-
.split_whitespace()
|
|
378
|
-
.find(|word| word.contains(pattern))
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// ✅ Good: Lifetime elision rules
|
|
383
|
-
// These functions don't need explicit lifetime annotations
|
|
384
|
-
|
|
385
|
-
// Rule 1: Each parameter gets its own lifetime
|
|
386
|
-
fn process_string(s: &str) -> String {
|
|
387
|
-
s.to_uppercase()
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Rule 2: If there's exactly one input lifetime, it's assigned to all outputs
|
|
391
|
-
fn get_first_char(s: &str) -> Option<&str> {
|
|
392
|
-
s.chars().next().map(|_| &s[0..1])
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Rule 3: If one parameter is &self or &mut self, its lifetime is assigned to all outputs
|
|
396
|
-
impl<'a> TextProcessor<'a> {
|
|
397
|
-
fn get_text(&self) -> &str {
|
|
398
|
-
self.text
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
fn get_first_processed(&self) -> Option<&str> {
|
|
402
|
-
self.processed.first().copied()
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// ✅ Good: Static lifetime for string literals and global data
|
|
407
|
-
static GLOBAL_CONFIG: &str = "production";
|
|
408
|
-
|
|
409
|
-
fn get_config() -> &'static str {
|
|
410
|
-
GLOBAL_CONFIG
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Function that returns a string literal (has 'static lifetime)
|
|
414
|
-
fn get_error_message() -> &'static str {
|
|
415
|
-
"An error occurred"
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// ✅ Good: Lifetime bounds in generics
|
|
419
|
-
fn process_and_store<'a, T>(data: &'a T, storage: &mut Vec<&'a T>)
|
|
420
|
-
where
|
|
421
|
-
T: std::fmt::Debug + 'a,
|
|
422
|
-
{
|
|
423
|
-
println!("Processing: {:?}", data);
|
|
424
|
-
storage.push(data);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Higher-ranked trait bounds (HRTB)
|
|
428
|
-
fn apply_to_all<F>(strings: &[String], f: F)
|
|
429
|
-
where
|
|
430
|
-
F: for<'a> Fn(&'a str) -> &'a str,
|
|
431
|
-
{
|
|
432
|
-
for s in strings {
|
|
433
|
-
let result = f(s);
|
|
434
|
-
println!("{}", result);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Usage examples
|
|
439
|
-
fn lifetime_examples() {
|
|
440
|
-
let text1 = "Hello world";
|
|
441
|
-
let text2 = "Hi";
|
|
442
|
-
|
|
443
|
-
let longer = longest(text1, text2);
|
|
444
|
-
println!("Longer: {}", longer);
|
|
445
|
-
|
|
446
|
-
let mut processor = TextProcessor::new("This is a sample text with some words");
|
|
447
|
-
processor.process_words();
|
|
448
|
-
|
|
449
|
-
for word in processor.get_processed() {
|
|
450
|
-
println!("Processed word: {}", word);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if let Some(found) = processor.find_in_text("sample") {
|
|
454
|
-
println!("Found word containing 'sample': {}", found);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### 2. Advanced Borrowing Patterns | 高级借用模式
|
|
460
|
-
|
|
461
|
-
```rust
|
|
462
|
-
use std::collections::HashMap;
|
|
463
|
-
|
|
464
|
-
// ✅ Good: Splitting borrows
|
|
465
|
-
struct Database {
|
|
466
|
-
users: HashMap<u64, User>,
|
|
467
|
-
sessions: HashMap<String, u64>,
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
impl Database {
|
|
471
|
-
fn new() -> Self {
|
|
472
|
-
Self {
|
|
473
|
-
users: HashMap::new(),
|
|
474
|
-
sessions: HashMap::new(),
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Split mutable borrows to avoid conflicts
|
|
479
|
-
fn get_users_and_sessions_mut(&mut self) -> (&mut HashMap<u64, User>, &mut HashMap<String, u64>) {
|
|
480
|
-
(&mut self.users, &mut self.sessions)
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Method that needs to borrow different parts
|
|
484
|
-
fn authenticate_and_update(&mut self, session_id: &str, new_email: String) -> Result<(), &'static str> {
|
|
485
|
-
// First, get the user ID from session
|
|
486
|
-
let user_id = self.sessions.get(session_id)
|
|
487
|
-
.copied()
|
|
488
|
-
.ok_or("Invalid session")?;
|
|
489
|
-
|
|
490
|
-
// Then update the user - this works because we're not holding a reference to sessions
|
|
491
|
-
let user = self.users.get_mut(&user_id)
|
|
492
|
-
.ok_or("User not found")?;
|
|
493
|
-
|
|
494
|
-
user.update_email(new_email)?;
|
|
495
|
-
|
|
496
|
-
Ok(())
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// ✅ Good: Using entry API to avoid double lookups
|
|
501
|
-
impl Database {
|
|
502
|
-
fn get_or_create_user(&mut self, id: u64, name: String, email: String) -> &mut User {
|
|
503
|
-
self.users.entry(id).or_insert_with(|| User::new(id, name, email))
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
fn update_or_create_session(&mut self, session_id: String, user_id: u64) {
|
|
507
|
-
self.sessions.insert(session_id, user_id);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// ✅ Good: Iterator patterns that work with borrowing
|
|
512
|
-
impl Database {
|
|
513
|
-
fn find_users_by_email_domain(&self, domain: &str) -> impl Iterator<Item = &User> {
|
|
514
|
-
self.users.values()
|
|
515
|
-
.filter(move |user| user.email.ends_with(domain))
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
fn active_sessions(&self) -> impl Iterator<Item = (&String, &u64)> {
|
|
519
|
-
self.sessions.iter()
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// ✅ Good: Avoiding borrowing issues with cloning when necessary
|
|
524
|
-
#[derive(Debug, Clone)]
|
|
525
|
-
struct UserSummary {
|
|
526
|
-
id: u64,
|
|
527
|
-
name: String,
|
|
528
|
-
email_domain: String,
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
impl Database {
|
|
532
|
-
fn get_user_summaries(&self) -> Vec<UserSummary> {
|
|
533
|
-
self.users.values()
|
|
534
|
-
.map(|user| UserSummary {
|
|
535
|
-
id: user.id,
|
|
536
|
-
name: user.name.clone(),
|
|
537
|
-
email_domain: user.email.split('@').nth(1).unwrap_or("").to_string(),
|
|
538
|
-
})
|
|
539
|
-
.collect()
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// ✅ Good: Using Cow (Clone on Write) for efficiency
|
|
544
|
-
use std::borrow::Cow;
|
|
545
|
-
|
|
546
|
-
fn process_text(text: &str) -> Cow<str> {
|
|
547
|
-
if text.contains("bad_word") {
|
|
548
|
-
// Only clone/allocate if we need to modify
|
|
549
|
-
Cow::Owned(text.replace("bad_word", "***"))
|
|
550
|
-
} else {
|
|
551
|
-
// Return borrowed data if no modification needed
|
|
552
|
-
Cow::Borrowed(text)
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
fn cow_example() {
|
|
557
|
-
let clean_text = "This is clean text";
|
|
558
|
-
let dirty_text = "This contains bad_word";
|
|
559
|
-
|
|
560
|
-
let result1 = process_text(clean_text); // No allocation
|
|
561
|
-
let result2 = process_text(dirty_text); // Allocates new string
|
|
562
|
-
|
|
563
|
-
println!("Result 1: {}", result1);
|
|
564
|
-
println!("Result 2: {}", result2);
|
|
565
|
-
}
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
## Async/Await Patterns | Async/Await 模式
|
|
569
|
-
|
|
570
|
-
### 1. Basic Async Patterns | 基本异步模式
|
|
571
|
-
|
|
572
|
-
```rust
|
|
573
|
-
use tokio;
|
|
574
|
-
use std::time::Duration;
|
|
575
|
-
use futures::future::{join, join_all, select, Either};
|
|
576
|
-
|
|
577
|
-
// ✅ Good: Basic async function
|
|
578
|
-
async fn fetch_user_data(user_id: u64) -> Result<User, Box<dyn std::error::Error>> {
|
|
579
|
-
// Simulate network delay
|
|
580
|
-
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
581
|
-
|
|
582
|
-
// Simulate fetching from database
|
|
583
|
-
Ok(User::new(user_id, "Alice".to_string(), "alice@example.com".to_string()))
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// ✅ Good: Async method in impl block
|
|
587
|
-
struct UserService {
|
|
588
|
-
base_url: String,
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
impl UserService {
|
|
592
|
-
fn new(base_url: String) -> Self {
|
|
593
|
-
Self { base_url }
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
async fn get_user(&self, id: u64) -> Result<User, Box<dyn std::error::Error>> {
|
|
597
|
-
let url = format!("{}/users/{}", self.base_url, id);
|
|
598
|
-
|
|
599
|
-
// Simulate HTTP request
|
|
600
|
-
tokio::time::sleep(Duration::from_millis(50)).await;
|
|
601
|
-
|
|
602
|
-
fetch_user_data(id).await
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
async fn create_user(&self, name: String, email: String) -> Result<User, Box<dyn std::error::Error>> {
|
|
606
|
-
// Simulate validation
|
|
607
|
-
if name.is_empty() || email.is_empty() {
|
|
608
|
-
return Err("Name and email are required".into());
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Simulate HTTP POST
|
|
612
|
-
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
613
|
-
|
|
614
|
-
Ok(User::new(1, name, email))
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
// ✅ Good: Concurrent execution with join
|
|
619
|
-
async fn fetch_multiple_users(ids: Vec<u64>) -> Vec<Result<User, Box<dyn std::error::Error>>> {
|
|
620
|
-
let futures: Vec<_> = ids.into_iter()
|
|
621
|
-
.map(|id| fetch_user_data(id))
|
|
622
|
-
.collect();
|
|
623
|
-
|
|
624
|
-
join_all(futures).await
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// ✅ Good: Racing futures with select
|
|
628
|
-
async fn fetch_with_timeout(user_id: u64) -> Result<User, &'static str> {
|
|
629
|
-
let fetch_future = fetch_user_data(user_id);
|
|
630
|
-
let timeout_future = tokio::time::sleep(Duration::from_secs(5));
|
|
631
|
-
|
|
632
|
-
match select(fetch_future, timeout_future).await {
|
|
633
|
-
Either::Left((result, _)) => result.map_err(|_| "Fetch failed"),
|
|
634
|
-
Either::Right((_, _)) => Err("Timeout"),
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// ✅ Good: Async iterator pattern
|
|
639
|
-
use futures::stream::{self, StreamExt};
|
|
640
|
-
|
|
641
|
-
async fn process_users_stream(user_ids: Vec<u64>) {
|
|
642
|
-
let user_stream = stream::iter(user_ids)
|
|
643
|
-
.map(|id| async move {
|
|
644
|
-
fetch_user_data(id).await
|
|
645
|
-
})
|
|
646
|
-
.buffer_unordered(5); // Process up to 5 concurrently
|
|
647
|
-
|
|
648
|
-
user_stream
|
|
649
|
-
.for_each(|result| async {
|
|
650
|
-
match result {
|
|
651
|
-
Ok(user) => println!("Processed user: {}", user.display_info()),
|
|
652
|
-
Err(e) => eprintln!("Error processing user: {}", e),
|
|
653
|
-
}
|
|
654
|
-
})
|
|
655
|
-
.await;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
#[tokio::main]
|
|
659
|
-
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
660
|
-
let service = UserService::new("https://api.example.com".to_string());
|
|
661
|
-
|
|
662
|
-
// Sequential execution
|
|
663
|
-
let user1 = service.get_user(1).await?;
|
|
664
|
-
println!("User 1: {}", user1.display_info());
|
|
665
|
-
|
|
666
|
-
// Concurrent execution
|
|
667
|
-
let (user2_result, user3_result) = join(
|
|
668
|
-
service.get_user(2),
|
|
669
|
-
service.get_user(3)
|
|
670
|
-
).await;
|
|
671
|
-
|
|
672
|
-
if let Ok(user2) = user2_result {
|
|
673
|
-
println!("User 2: {}", user2.display_info());
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
if let Ok(user3) = user3_result {
|
|
677
|
-
println!("User 3: {}", user3.display_info());
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// Fetch multiple users concurrently
|
|
681
|
-
let user_ids = vec![4, 5, 6, 7, 8];
|
|
682
|
-
let results = fetch_multiple_users(user_ids).await;
|
|
683
|
-
|
|
684
|
-
for (i, result) in results.into_iter().enumerate() {
|
|
685
|
-
match result {
|
|
686
|
-
Ok(user) => println!("User {}: {}", i + 4, user.display_info()),
|
|
687
|
-
Err(e) => eprintln!("Error fetching user {}: {}", i + 4, e),
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// Process users with streaming
|
|
692
|
-
let stream_ids = vec![9, 10, 11, 12, 13];
|
|
693
|
-
process_users_stream(stream_ids).await;
|
|
694
|
-
|
|
695
|
-
Ok(())
|
|
696
|
-
}
|
|
697
|
-
```
|
|
698
|
-
|
|
699
|
-
### 2. Advanced Async Patterns | 高级异步模式
|
|
700
|
-
|
|
701
|
-
```rust
|
|
702
|
-
use tokio::sync::{mpsc, oneshot, Mutex, RwLock};
|
|
703
|
-
use std::sync::Arc;
|
|
704
|
-
use std::collections::HashMap;
|
|
705
|
-
|
|
706
|
-
// ✅ Good: Actor pattern with message passing
|
|
707
|
-
#[derive(Debug)]
|
|
708
|
-
enum UserMessage {
|
|
709
|
-
Get { id: u64, respond_to: oneshot::Sender<Option<User>> },
|
|
710
|
-
Create { user: User, respond_to: oneshot::Sender<Result<(), String>> },
|
|
711
|
-
Update { id: u64, email: String, respond_to: oneshot::Sender<Result<(), String>> },
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
struct UserActor {
|
|
715
|
-
receiver: mpsc::Receiver<UserMessage>,
|
|
716
|
-
users: HashMap<u64, User>,
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
impl UserActor {
|
|
720
|
-
fn new(receiver: mpsc::Receiver<UserMessage>) -> Self {
|
|
721
|
-
Self {
|
|
722
|
-
receiver,
|
|
723
|
-
users: HashMap::new(),
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
async fn run(&mut self) {
|
|
728
|
-
while let Some(msg) = self.receiver.recv().await {
|
|
729
|
-
match msg {
|
|
730
|
-
UserMessage::Get { id, respond_to } => {
|
|
731
|
-
let user = self.users.get(&id).cloned();
|
|
732
|
-
let _ = respond_to.send(user);
|
|
733
|
-
}
|
|
734
|
-
UserMessage::Create { user, respond_to } => {
|
|
735
|
-
let id = user.id;
|
|
736
|
-
self.users.insert(id, user);
|
|
737
|
-
let _ = respond_to.send(Ok(()));
|
|
738
|
-
}
|
|
739
|
-
UserMessage::Update { id, email, respond_to } => {
|
|
740
|
-
if let Some(user) = self.users.get_mut(&id) {
|
|
741
|
-
match user.update_email(email) {
|
|
742
|
-
Ok(()) => { let _ = respond_to.send(Ok(())); }
|
|
743
|
-
Err(e) => { let _ = respond_to.send(Err(e.to_string())); }
|
|
744
|
-
}
|
|
745
|
-
} else {
|
|
746
|
-
let _ = respond_to.send(Err("User not found".to_string()));
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// Handle for communicating with the actor
|
|
755
|
-
#[derive(Clone)]
|
|
756
|
-
struct UserActorHandle {
|
|
757
|
-
sender: mpsc::Sender<UserMessage>,
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
impl UserActorHandle {
|
|
761
|
-
fn new() -> Self {
|
|
762
|
-
let (sender, receiver) = mpsc::channel(100);
|
|
763
|
-
let mut actor = UserActor::new(receiver);
|
|
764
|
-
|
|
765
|
-
tokio::spawn(async move {
|
|
766
|
-
actor.run().await;
|
|
767
|
-
});
|
|
768
|
-
|
|
769
|
-
Self { sender }
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
async fn get_user(&self, id: u64) -> Option<User> {
|
|
773
|
-
let (send, recv) = oneshot::channel();
|
|
774
|
-
let msg = UserMessage::Get { id, respond_to: send };
|
|
775
|
-
|
|
776
|
-
if self.sender.send(msg).await.is_ok() {
|
|
777
|
-
recv.await.unwrap_or(None)
|
|
778
|
-
} else {
|
|
779
|
-
None
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
async fn create_user(&self, user: User) -> Result<(), String> {
|
|
784
|
-
let (send, recv) = oneshot::channel();
|
|
785
|
-
let msg = UserMessage::Create { user, respond_to: send };
|
|
786
|
-
|
|
787
|
-
if self.sender.send(msg).await.is_ok() {
|
|
788
|
-
recv.await.unwrap_or(Err("Actor unavailable".to_string()))
|
|
789
|
-
} else {
|
|
790
|
-
Err("Failed to send message".to_string())
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
// ✅ Good: Shared state with async locks
|
|
796
|
-
#[derive(Clone)]
|
|
797
|
-
struct AsyncUserRepository {
|
|
798
|
-
users: Arc<RwLock<HashMap<u64, User>>>,
|
|
799
|
-
next_id: Arc<Mutex<u64>>,
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
impl AsyncUserRepository {
|
|
803
|
-
fn new() -> Self {
|
|
804
|
-
Self {
|
|
805
|
-
users: Arc::new(RwLock::new(HashMap::new())),
|
|
806
|
-
next_id: Arc::new(Mutex::new(1)),
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
async fn create_user(&self, name: String, email: String) -> u64 {
|
|
811
|
-
let mut next_id = self.next_id.lock().await;
|
|
812
|
-
let id = *next_id;
|
|
813
|
-
*next_id += 1;
|
|
814
|
-
drop(next_id); // Release lock early
|
|
815
|
-
|
|
816
|
-
let user = User::new(id, name, email);
|
|
817
|
-
let mut users = self.users.write().await;
|
|
818
|
-
users.insert(id, user);
|
|
819
|
-
|
|
820
|
-
id
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
async fn get_user(&self, id: u64) -> Option<User> {
|
|
824
|
-
let users = self.users.read().await;
|
|
825
|
-
users.get(&id).cloned()
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
async fn update_user_email(&self, id: u64, new_email: String) -> Result<(), String> {
|
|
829
|
-
let mut users = self.users.write().await;
|
|
830
|
-
if let Some(user) = users.get_mut(&id) {
|
|
831
|
-
user.update_email(new_email).map_err(|e| e.to_string())
|
|
832
|
-
} else {
|
|
833
|
-
Err("User not found".to_string())
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// ✅ Good: Background task pattern
|
|
839
|
-
async fn background_cleanup_task(repo: AsyncUserRepository) {
|
|
840
|
-
let mut interval = tokio::time::interval(Duration::from_secs(60));
|
|
841
|
-
|
|
842
|
-
loop {
|
|
843
|
-
interval.tick().await;
|
|
844
|
-
|
|
845
|
-
// Simulate cleanup logic
|
|
846
|
-
println!("Running background cleanup...");
|
|
847
|
-
|
|
848
|
-
// In a real application, you might clean up expired sessions,
|
|
849
|
-
// remove inactive users, etc.
|
|
850
|
-
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// Usage example
|
|
855
|
-
async fn async_patterns_example() -> Result<(), Box<dyn std::error::Error>> {
|
|
856
|
-
// Actor pattern
|
|
857
|
-
let user_actor = UserActorHandle::new();
|
|
858
|
-
|
|
859
|
-
let user = User::new(1, "Alice".to_string(), "alice@example.com".to_string());
|
|
860
|
-
user_actor.create_user(user).await?;
|
|
861
|
-
|
|
862
|
-
if let Some(retrieved_user) = user_actor.get_user(1).await {
|
|
863
|
-
println!("Retrieved user: {}", retrieved_user.display_info());
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// Shared state pattern
|
|
867
|
-
let repo = AsyncUserRepository::new();
|
|
868
|
-
|
|
869
|
-
// Spawn background task
|
|
870
|
-
let repo_clone = repo.clone();
|
|
871
|
-
tokio::spawn(async move {
|
|
872
|
-
background_cleanup_task(repo_clone).await;
|
|
873
|
-
});
|
|
874
|
-
|
|
875
|
-
// Use repository
|
|
876
|
-
let user_id = repo.create_user("Bob".to_string(), "bob@example.com".to_string()).await;
|
|
877
|
-
println!("Created user with ID: {}", user_id);
|
|
878
|
-
|
|
879
|
-
if let Some(user) = repo.get_user(user_id).await {
|
|
880
|
-
println!("Found user: {}", user.display_info());
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
Ok(())
|
|
884
|
-
}
|
|
885
|
-
```
|
|
886
|
-
|
|
887
|
-
## Error Handling | 错误处理
|
|
888
|
-
|
|
889
|
-
### 1. Custom Error Types | 自定义错误类型
|
|
890
|
-
|
|
891
|
-
```rust
|
|
892
|
-
use std::fmt;
|
|
893
|
-
|
|
894
|
-
// ✅ Good: Custom error type with proper Display and Debug
|
|
895
|
-
#[derive(Debug)]
|
|
896
|
-
enum UserError {
|
|
897
|
-
NotFound(u64),
|
|
898
|
-
InvalidEmail(String),
|
|
899
|
-
DatabaseError(String),
|
|
900
|
-
ValidationError { field: String, message: String },
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
impl fmt::Display for UserError {
|
|
904
|
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
905
|
-
match self {
|
|
906
|
-
UserError::NotFound(id) => write!(f, "User with ID {} not found", id),
|
|
907
|
-
UserError::InvalidEmail(email) => write!(f, "Invalid email address: {}", email),
|
|
908
|
-
UserError::DatabaseError(msg) => write!(f, "Database error: {}", msg),
|
|
909
|
-
UserError::ValidationError { field, message } => {
|
|
910
|
-
write!(f, "Validation error on field '{}': {}", field, message)
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
impl std::error::Error for UserError {}
|
|
917
|
-
|
|
918
|
-
// ✅ Good: Result type alias for convenience
|
|
919
|
-
type UserResult<T> = Result<T, UserError>;
|
|
920
|
-
|
|
921
|
-
// ✅ Good: Using ? operator with custom errors
|
|
922
|
-
impl UserRepository {
|
|
923
|
-
fn validate_email(email: &str) -> UserResult<()> {
|
|
924
|
-
if email.is_empty() {
|
|
925
|
-
return Err(UserError::ValidationError {
|
|
926
|
-
field: "email".to_string(),
|
|
927
|
-
message: "cannot be empty".to_string(),
|
|
928
|
-
});
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
if !email.contains('@') {
|
|
932
|
-
return Err(UserError::InvalidEmail(email.to_string()));
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
Ok(())
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
fn create_user_safe(&mut self, name: String, email: String) -> UserResult<u64> {
|
|
939
|
-
// Validate input
|
|
940
|
-
if name.is_empty() {
|
|
941
|
-
return Err(UserError::ValidationError {
|
|
942
|
-
field: "name".to_string(),
|
|
943
|
-
message: "cannot be empty".to_string(),
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
Self::validate_email(&email)?; // Using ? operator
|
|
948
|
-
|
|
949
|
-
// Check for duplicates
|
|
950
|
-
for user in self.users.values() {
|
|
951
|
-
if user.email == email {
|
|
952
|
-
return Err(UserError::ValidationError {
|
|
953
|
-
field: "email".to_string(),
|
|
954
|
-
message: "already exists".to_string(),
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
// Create user
|
|
960
|
-
let id = self.next_id;
|
|
961
|
-
self.next_id += 1;
|
|
962
|
-
|
|
963
|
-
let user = User::new(id, name, email);
|
|
964
|
-
self.users.insert(id, user);
|
|
965
|
-
|
|
966
|
-
Ok(id)
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
fn get_user_safe(&self, id: u64) -> UserResult<&User> {
|
|
970
|
-
self.users.get(&id).ok_or(UserError::NotFound(id))
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
```
|
|
974
|
-
|
|
975
|
-
## Performance Patterns | 性能模式
|
|
976
|
-
|
|
977
|
-
### 1. Zero-Cost Abstractions | 零成本抽象
|
|
978
|
-
|
|
979
|
-
```rust
|
|
980
|
-
// ✅ Good: Iterator chains compile to efficient loops
|
|
981
|
-
fn process_numbers_efficiently(numbers: &[i32]) -> Vec<i32> {
|
|
982
|
-
numbers
|
|
983
|
-
.iter()
|
|
984
|
-
.filter(|&&x| x > 0)
|
|
985
|
-
.map(|&x| x * 2)
|
|
986
|
-
.collect()
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
// ✅ Good: Using iterators instead of indexing
|
|
990
|
-
fn sum_positive_numbers(numbers: &[i32]) -> i32 {
|
|
991
|
-
numbers.iter().filter(|&&x| x > 0).sum()
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
// ✅ Good: Avoiding allocations with iterator adaptors
|
|
995
|
-
fn find_first_large_number(numbers: &[i32]) -> Option<i32> {
|
|
996
|
-
numbers
|
|
997
|
-
.iter()
|
|
998
|
-
.filter(|&&x| x > 1000)
|
|
999
|
-
.copied()
|
|
1000
|
-
.next()
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
// ✅ Good: Using Vec::with_capacity when size is known
|
|
1004
|
-
fn create_processed_data(input: &[i32]) -> Vec<String> {
|
|
1005
|
-
let mut result = Vec::with_capacity(input.len());
|
|
1006
|
-
|
|
1007
|
-
for &num in input {
|
|
1008
|
-
result.push(format!("Number: {}", num));
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
result
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
// ✅ Good: String building with capacity
|
|
1015
|
-
fn build_report(items: &[&str]) -> String {
|
|
1016
|
-
let total_len: usize = items.iter().map(|s| s.len()).sum();
|
|
1017
|
-
let mut report = String::with_capacity(total_len + items.len() * 10); // Extra space for formatting
|
|
1018
|
-
|
|
1019
|
-
for item in items {
|
|
1020
|
-
report.push_str("Item: ");
|
|
1021
|
-
report.push_str(item);
|
|
1022
|
-
report.push('\n');
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
report
|
|
1026
|
-
}
|
|
1027
|
-
```
|
|
1028
|
-
|
|
1029
|
-
## Code Quality Checklist | 代码质量检查清单
|
|
1030
|
-
|
|
1031
|
-
- [ ] Ownership is clear and minimal cloning is used
|
|
1032
|
-
- [ ] Lifetimes are properly annotated where needed
|
|
1033
|
-
- [ ] Borrowing rules are followed without fighting the borrow checker
|
|
1034
|
-
- [ ] Error handling uses Result types and proper error propagation
|
|
1035
|
-
- [ ] Async code uses proper concurrency patterns
|
|
1036
|
-
- [ ] Smart pointers (Rc, Arc, Box) are used appropriately
|
|
1037
|
-
- [ ] Iterator chains are preferred over manual loops
|
|
1038
|
-
- [ ] Memory allocations are minimized with pre-allocation
|
|
1039
|
-
- [ ] Thread safety is ensured with proper synchronization primitives
|
|
1040
|
-
- [ ] Code compiles without warnings
|
|
1041
|
-
- [ ] Tests cover both success and error cases
|
|
1042
|
-
- [ ] Documentation includes examples and safety notes
|
|
1043
|
-
|
|
1044
|
-
## 代码质量检查清单
|
|
1045
|
-
|
|
1046
|
-
- [ ] 所有权清晰,最少使用克隆
|
|
1047
|
-
- [ ] 在需要的地方正确注解生命周期
|
|
1048
|
-
- [ ] 遵循借用规则,不与借用检查器对抗
|
|
1049
|
-
- [ ] 错误处理使用 Result 类型和适当的错误传播
|
|
1050
|
-
- [ ] 异步代码使用适当的并发模式
|
|
1051
|
-
- [ ] 智能指针(Rc、Arc、Box)使用得当
|
|
1052
|
-
- [ ] 优先使用迭代器链而不是手动循环
|
|
1053
|
-
- [ ] 通过预分配最小化内存分配
|
|
1054
|
-
- [ ] 使用适当的同步原语确保线程安全
|
|
1055
|
-
- [ ] 代码编译无警告
|
|
1056
|
-
- [ ] 测试覆盖成功和错误情况
|
|
1057
|
-
- [ ] 文档包含示例和安全说明
|