locus-product-planning 1.0.0 → 1.1.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/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +32 -0
- package/README.md +127 -45
- package/agents/engineering/architect-reviewer.md +122 -0
- package/agents/engineering/engineering-manager.md +101 -0
- package/agents/engineering/principal-engineer.md +98 -0
- package/agents/engineering/staff-engineer.md +86 -0
- package/agents/engineering/tech-lead.md +114 -0
- package/agents/executive/ceo-strategist.md +81 -0
- package/agents/executive/cfo-analyst.md +97 -0
- package/agents/executive/coo-operations.md +100 -0
- package/agents/executive/cpo-product.md +104 -0
- package/agents/executive/cto-architect.md +90 -0
- package/agents/product/product-manager.md +70 -0
- package/agents/product/project-manager.md +95 -0
- package/agents/product/qa-strategist.md +132 -0
- package/agents/product/scrum-master.md +70 -0
- package/dist/index.d.ts +10 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -95
- package/dist/lib/skills-core.d.ts +95 -0
- package/dist/lib/skills-core.d.ts.map +1 -0
- package/dist/lib/skills-core.js +361 -0
- package/hooks/hooks.json +15 -0
- package/hooks/run-hook.cmd +32 -0
- package/hooks/session-start.cmd +13 -0
- package/hooks/session-start.sh +70 -0
- package/opencode.json +11 -7
- package/package.json +18 -4
- package/skills/01-executive-suite/ceo-strategist/SKILL.md +132 -0
- package/skills/01-executive-suite/cfo-analyst/SKILL.md +187 -0
- package/skills/01-executive-suite/coo-operations/SKILL.md +211 -0
- package/skills/01-executive-suite/cpo-product/SKILL.md +231 -0
- package/skills/01-executive-suite/cto-architect/SKILL.md +173 -0
- package/skills/02-product-management/estimation-expert/SKILL.md +139 -0
- package/skills/02-product-management/product-manager/SKILL.md +265 -0
- package/skills/02-product-management/program-manager/SKILL.md +178 -0
- package/skills/02-product-management/project-manager/SKILL.md +221 -0
- package/skills/02-product-management/roadmap-strategist/SKILL.md +186 -0
- package/skills/02-product-management/scrum-master/SKILL.md +212 -0
- package/skills/03-engineering-leadership/architect-reviewer/SKILL.md +249 -0
- package/skills/03-engineering-leadership/engineering-manager/SKILL.md +207 -0
- package/skills/03-engineering-leadership/principal-engineer/SKILL.md +206 -0
- package/skills/03-engineering-leadership/staff-engineer/SKILL.md +237 -0
- package/skills/03-engineering-leadership/tech-lead/SKILL.md +296 -0
- package/skills/04-developer-specializations/core/backend-developer/SKILL.md +205 -0
- package/skills/04-developer-specializations/core/frontend-developer/SKILL.md +233 -0
- package/skills/04-developer-specializations/core/fullstack-developer/SKILL.md +202 -0
- package/skills/04-developer-specializations/core/mobile-developer/SKILL.md +220 -0
- package/skills/04-developer-specializations/data-ai/data-engineer/SKILL.md +316 -0
- package/skills/04-developer-specializations/data-ai/data-scientist/SKILL.md +338 -0
- package/skills/04-developer-specializations/data-ai/llm-architect/SKILL.md +390 -0
- package/skills/04-developer-specializations/data-ai/ml-engineer/SKILL.md +349 -0
- package/skills/04-developer-specializations/infrastructure/cloud-architect/SKILL.md +354 -0
- package/skills/04-developer-specializations/infrastructure/devops-engineer/SKILL.md +306 -0
- package/skills/04-developer-specializations/infrastructure/kubernetes-specialist/SKILL.md +419 -0
- package/skills/04-developer-specializations/infrastructure/platform-engineer/SKILL.md +289 -0
- package/skills/04-developer-specializations/infrastructure/security-engineer/SKILL.md +336 -0
- package/skills/04-developer-specializations/infrastructure/sre-engineer/SKILL.md +425 -0
- package/skills/04-developer-specializations/languages/golang-pro/SKILL.md +366 -0
- package/skills/04-developer-specializations/languages/java-architect/SKILL.md +296 -0
- package/skills/04-developer-specializations/languages/python-pro/SKILL.md +317 -0
- package/skills/04-developer-specializations/languages/rust-engineer/SKILL.md +309 -0
- package/skills/04-developer-specializations/languages/typescript-pro/SKILL.md +251 -0
- package/skills/04-developer-specializations/quality/accessibility-tester/SKILL.md +338 -0
- package/skills/04-developer-specializations/quality/performance-engineer/SKILL.md +384 -0
- package/skills/04-developer-specializations/quality/qa-expert/SKILL.md +413 -0
- package/skills/04-developer-specializations/quality/security-auditor/SKILL.md +359 -0
- package/skills/05-specialists/compliance-specialist/SKILL.md +171 -0
- package/skills/using-locus/SKILL.md +124 -0
- package/.opencode/skills/locus/SKILL.md +0 -299
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python-pro
|
|
3
|
+
description: Advanced Python expertise including type hints, async programming, performance optimization, packaging, and Pythonic patterns
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: languages
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Python Pro
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a Python expert with deep knowledge of the language, its ecosystem, and best practices for building robust, maintainable Python applications.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing Python applications and libraries
|
|
19
|
+
- Implementing type hints and static analysis
|
|
20
|
+
- Writing async Python code
|
|
21
|
+
- Optimizing Python performance
|
|
22
|
+
- Setting up Python project structure
|
|
23
|
+
- Debugging complex Python issues
|
|
24
|
+
- Reviewing Python code quality
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Modern Python
|
|
29
|
+
- Type hints and typing module
|
|
30
|
+
- async/await patterns
|
|
31
|
+
- Context managers and decorators
|
|
32
|
+
- Dataclasses and attrs
|
|
33
|
+
- Pattern matching (3.10+)
|
|
34
|
+
|
|
35
|
+
### 2. Project Structure
|
|
36
|
+
- Package and module design
|
|
37
|
+
- Dependency management (poetry, pip-tools)
|
|
38
|
+
- Virtual environments
|
|
39
|
+
- pyproject.toml configuration
|
|
40
|
+
- Publishing to PyPI
|
|
41
|
+
|
|
42
|
+
### 3. Performance
|
|
43
|
+
- Profiling and benchmarking
|
|
44
|
+
- Memory optimization
|
|
45
|
+
- C extensions and Cython
|
|
46
|
+
- Multiprocessing vs threading vs async
|
|
47
|
+
- Generator patterns
|
|
48
|
+
|
|
49
|
+
### 4. Testing & Quality
|
|
50
|
+
- pytest and fixtures
|
|
51
|
+
- Property-based testing (hypothesis)
|
|
52
|
+
- Type checking (mypy, pyright)
|
|
53
|
+
- Linting (ruff, flake8)
|
|
54
|
+
- Code formatting (black, ruff)
|
|
55
|
+
|
|
56
|
+
## Type Hints
|
|
57
|
+
|
|
58
|
+
### Basic Types
|
|
59
|
+
```python
|
|
60
|
+
from typing import Optional, Union, List, Dict, Callable, TypeVar
|
|
61
|
+
|
|
62
|
+
def process_items(
|
|
63
|
+
items: list[str],
|
|
64
|
+
callback: Callable[[str], None],
|
|
65
|
+
config: dict[str, int] | None = None
|
|
66
|
+
) -> list[str]:
|
|
67
|
+
...
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Generics
|
|
71
|
+
```python
|
|
72
|
+
from typing import TypeVar, Generic
|
|
73
|
+
|
|
74
|
+
T = TypeVar('T')
|
|
75
|
+
K = TypeVar('K')
|
|
76
|
+
V = TypeVar('V')
|
|
77
|
+
|
|
78
|
+
class Cache(Generic[K, V]):
|
|
79
|
+
def __init__(self) -> None:
|
|
80
|
+
self._data: dict[K, V] = {}
|
|
81
|
+
|
|
82
|
+
def get(self, key: K) -> V | None:
|
|
83
|
+
return self._data.get(key)
|
|
84
|
+
|
|
85
|
+
def set(self, key: K, value: V) -> None:
|
|
86
|
+
self._data[key] = value
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Protocols (Structural Subtyping)
|
|
90
|
+
```python
|
|
91
|
+
from typing import Protocol
|
|
92
|
+
|
|
93
|
+
class Readable(Protocol):
|
|
94
|
+
def read(self) -> str: ...
|
|
95
|
+
|
|
96
|
+
class Writable(Protocol):
|
|
97
|
+
def write(self, data: str) -> None: ...
|
|
98
|
+
|
|
99
|
+
def copy_data(src: Readable, dst: Writable) -> None:
|
|
100
|
+
dst.write(src.read())
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### TypedDict
|
|
104
|
+
```python
|
|
105
|
+
from typing import TypedDict, NotRequired
|
|
106
|
+
|
|
107
|
+
class UserDict(TypedDict):
|
|
108
|
+
id: int
|
|
109
|
+
name: str
|
|
110
|
+
email: str
|
|
111
|
+
bio: NotRequired[str] # Optional field
|
|
112
|
+
|
|
113
|
+
def create_user(data: UserDict) -> User:
|
|
114
|
+
...
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Async Patterns
|
|
118
|
+
|
|
119
|
+
### Basic Async
|
|
120
|
+
```python
|
|
121
|
+
import asyncio
|
|
122
|
+
from typing import AsyncIterator
|
|
123
|
+
|
|
124
|
+
async def fetch_data(url: str) -> dict:
|
|
125
|
+
async with aiohttp.ClientSession() as session:
|
|
126
|
+
async with session.get(url) as response:
|
|
127
|
+
return await response.json()
|
|
128
|
+
|
|
129
|
+
async def fetch_all(urls: list[str]) -> list[dict]:
|
|
130
|
+
return await asyncio.gather(*[fetch_data(url) for url in urls])
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Async Context Managers
|
|
134
|
+
```python
|
|
135
|
+
from contextlib import asynccontextmanager
|
|
136
|
+
from typing import AsyncIterator
|
|
137
|
+
|
|
138
|
+
@asynccontextmanager
|
|
139
|
+
async def managed_connection() -> AsyncIterator[Connection]:
|
|
140
|
+
conn = await create_connection()
|
|
141
|
+
try:
|
|
142
|
+
yield conn
|
|
143
|
+
finally:
|
|
144
|
+
await conn.close()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Async Generators
|
|
148
|
+
```python
|
|
149
|
+
async def stream_data(source: Source) -> AsyncIterator[Data]:
|
|
150
|
+
async for chunk in source.read_chunks():
|
|
151
|
+
yield process(chunk)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Project Structure
|
|
155
|
+
|
|
156
|
+
### Recommended Layout
|
|
157
|
+
```
|
|
158
|
+
my_project/
|
|
159
|
+
├── pyproject.toml # Project config
|
|
160
|
+
├── README.md
|
|
161
|
+
├── src/
|
|
162
|
+
│ └── my_project/
|
|
163
|
+
│ ├── __init__.py
|
|
164
|
+
│ ├── main.py
|
|
165
|
+
│ ├── models/
|
|
166
|
+
│ ├── services/
|
|
167
|
+
│ └── utils/
|
|
168
|
+
├── tests/
|
|
169
|
+
│ ├── conftest.py
|
|
170
|
+
│ ├── unit/
|
|
171
|
+
│ └── integration/
|
|
172
|
+
└── scripts/
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### pyproject.toml
|
|
176
|
+
```toml
|
|
177
|
+
[project]
|
|
178
|
+
name = "my-project"
|
|
179
|
+
version = "0.1.0"
|
|
180
|
+
requires-python = ">=3.11"
|
|
181
|
+
dependencies = [
|
|
182
|
+
"fastapi>=0.100.0",
|
|
183
|
+
"pydantic>=2.0.0",
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
[project.optional-dependencies]
|
|
187
|
+
dev = [
|
|
188
|
+
"pytest>=7.0.0",
|
|
189
|
+
"mypy>=1.0.0",
|
|
190
|
+
"ruff>=0.1.0",
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
[tool.ruff]
|
|
194
|
+
line-length = 100
|
|
195
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
196
|
+
|
|
197
|
+
[tool.mypy]
|
|
198
|
+
strict = true
|
|
199
|
+
python_version = "3.11"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Pythonic Patterns
|
|
203
|
+
|
|
204
|
+
### Context Managers
|
|
205
|
+
```python
|
|
206
|
+
from contextlib import contextmanager
|
|
207
|
+
from typing import Iterator
|
|
208
|
+
|
|
209
|
+
@contextmanager
|
|
210
|
+
def timer(name: str) -> Iterator[None]:
|
|
211
|
+
start = time.perf_counter()
|
|
212
|
+
try:
|
|
213
|
+
yield
|
|
214
|
+
finally:
|
|
215
|
+
elapsed = time.perf_counter() - start
|
|
216
|
+
print(f"{name}: {elapsed:.3f}s")
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Decorators
|
|
220
|
+
```python
|
|
221
|
+
from functools import wraps
|
|
222
|
+
from typing import TypeVar, Callable, ParamSpec
|
|
223
|
+
|
|
224
|
+
P = ParamSpec('P')
|
|
225
|
+
R = TypeVar('R')
|
|
226
|
+
|
|
227
|
+
def retry(max_attempts: int = 3) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
228
|
+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
|
229
|
+
@wraps(func)
|
|
230
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
231
|
+
for attempt in range(max_attempts):
|
|
232
|
+
try:
|
|
233
|
+
return func(*args, **kwargs)
|
|
234
|
+
except Exception:
|
|
235
|
+
if attempt == max_attempts - 1:
|
|
236
|
+
raise
|
|
237
|
+
raise RuntimeError("Unreachable")
|
|
238
|
+
return wrapper
|
|
239
|
+
return decorator
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Dataclasses
|
|
243
|
+
```python
|
|
244
|
+
from dataclasses import dataclass, field
|
|
245
|
+
from datetime import datetime
|
|
246
|
+
|
|
247
|
+
@dataclass
|
|
248
|
+
class User:
|
|
249
|
+
id: int
|
|
250
|
+
name: str
|
|
251
|
+
email: str
|
|
252
|
+
created_at: datetime = field(default_factory=datetime.now)
|
|
253
|
+
tags: list[str] = field(default_factory=list)
|
|
254
|
+
|
|
255
|
+
def __post_init__(self) -> None:
|
|
256
|
+
self.email = self.email.lower()
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Performance Optimization
|
|
260
|
+
|
|
261
|
+
### Profiling
|
|
262
|
+
```python
|
|
263
|
+
import cProfile
|
|
264
|
+
import pstats
|
|
265
|
+
|
|
266
|
+
def profile(func):
|
|
267
|
+
profiler = cProfile.Profile()
|
|
268
|
+
profiler.enable()
|
|
269
|
+
result = func()
|
|
270
|
+
profiler.disable()
|
|
271
|
+
stats = pstats.Stats(profiler).sort_stats('cumtime')
|
|
272
|
+
stats.print_stats(20)
|
|
273
|
+
return result
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Memory Efficiency
|
|
277
|
+
```python
|
|
278
|
+
# Use generators for large datasets
|
|
279
|
+
def process_large_file(path: str) -> Iterator[dict]:
|
|
280
|
+
with open(path) as f:
|
|
281
|
+
for line in f:
|
|
282
|
+
yield json.loads(line)
|
|
283
|
+
|
|
284
|
+
# Use __slots__ for memory-heavy classes
|
|
285
|
+
class Point:
|
|
286
|
+
__slots__ = ('x', 'y')
|
|
287
|
+
|
|
288
|
+
def __init__(self, x: float, y: float) -> None:
|
|
289
|
+
self.x = x
|
|
290
|
+
self.y = y
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Anti-Patterns to Avoid
|
|
294
|
+
|
|
295
|
+
| Anti-Pattern | Why Bad | Better Approach |
|
|
296
|
+
|--------------|---------|-----------------|
|
|
297
|
+
| Mutable default args | Shared across calls | Use `None` and `field()` |
|
|
298
|
+
| Bare `except:` | Catches everything | Specific exceptions |
|
|
299
|
+
| `import *` | Namespace pollution | Explicit imports |
|
|
300
|
+
| Global variables | Hard to test | Dependency injection |
|
|
301
|
+
| No type hints | Harder to maintain | Add type hints |
|
|
302
|
+
| Ignoring mypy errors | Types not enforced | Fix the types |
|
|
303
|
+
|
|
304
|
+
## Constraints
|
|
305
|
+
|
|
306
|
+
- Always use type hints in public APIs
|
|
307
|
+
- Use `ruff` or `black` for formatting
|
|
308
|
+
- Run `mypy --strict` on new code
|
|
309
|
+
- Prefer `dataclass` over plain classes
|
|
310
|
+
- Use `pathlib` over `os.path`
|
|
311
|
+
- Prefer f-strings over `.format()`
|
|
312
|
+
|
|
313
|
+
## Related Skills
|
|
314
|
+
|
|
315
|
+
- `backend-developer` - Python web services
|
|
316
|
+
- `data-engineer` - Python data processing
|
|
317
|
+
- `ml-engineer` - Python ML/AI
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rust-engineer
|
|
3
|
+
description: Advanced Rust expertise including ownership, lifetimes, async patterns, unsafe code, macros, and systems programming best practices
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: languages
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Rust Engineer
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a Rust expert with deep knowledge of the ownership system, zero-cost abstractions, and best practices for building safe, performant systems software.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing Rust applications and libraries
|
|
19
|
+
- Working with ownership, borrowing, and lifetimes
|
|
20
|
+
- Writing async Rust code
|
|
21
|
+
- Optimizing for performance and memory
|
|
22
|
+
- Using unsafe Rust correctly
|
|
23
|
+
- Creating procedural macros
|
|
24
|
+
- Reviewing Rust code for safety and performance
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Ownership System
|
|
29
|
+
- Move semantics and borrowing
|
|
30
|
+
- Lifetime annotations
|
|
31
|
+
- Smart pointers (Box, Rc, Arc)
|
|
32
|
+
- Interior mutability (Cell, RefCell, Mutex)
|
|
33
|
+
- Drop trait and RAII
|
|
34
|
+
|
|
35
|
+
### 2. Type System
|
|
36
|
+
- Generics and trait bounds
|
|
37
|
+
- Associated types
|
|
38
|
+
- Trait objects vs generics
|
|
39
|
+
- Type-level programming
|
|
40
|
+
- PhantomData usage
|
|
41
|
+
|
|
42
|
+
### 3. Async Rust
|
|
43
|
+
- Futures and async/await
|
|
44
|
+
- Tokio/async-std runtime
|
|
45
|
+
- Pin and Unpin
|
|
46
|
+
- Cancellation safety
|
|
47
|
+
- Async trait patterns
|
|
48
|
+
|
|
49
|
+
### 4. Performance
|
|
50
|
+
- Zero-cost abstractions
|
|
51
|
+
- Stack vs heap allocation
|
|
52
|
+
- SIMD and vectorization
|
|
53
|
+
- Avoiding allocations
|
|
54
|
+
- Profiling and benchmarking
|
|
55
|
+
|
|
56
|
+
## Ownership Patterns
|
|
57
|
+
|
|
58
|
+
### Borrowing Strategies
|
|
59
|
+
```rust
|
|
60
|
+
// Prefer borrowing for read-only access
|
|
61
|
+
fn process(data: &Data) { /* ... */ }
|
|
62
|
+
|
|
63
|
+
// Use mutable borrow for modification
|
|
64
|
+
fn update(data: &mut Data) { /* ... */ }
|
|
65
|
+
|
|
66
|
+
// Take ownership when storing or when caller doesn't need it
|
|
67
|
+
fn consume(data: Data) { /* ... */ }
|
|
68
|
+
|
|
69
|
+
// Clone when you need your own copy
|
|
70
|
+
fn fork(data: &Data) -> ProcessedData {
|
|
71
|
+
let owned = data.clone();
|
|
72
|
+
// Process owned...
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Lifetime Annotations
|
|
77
|
+
```rust
|
|
78
|
+
// Explicit lifetime when return borrows from input
|
|
79
|
+
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
|
80
|
+
if x.len() > y.len() { x } else { y }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Struct with borrowed data
|
|
84
|
+
struct Parser<'a> {
|
|
85
|
+
input: &'a str,
|
|
86
|
+
position: usize,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
impl<'a> Parser<'a> {
|
|
90
|
+
fn new(input: &'a str) -> Self {
|
|
91
|
+
Self { input, position: 0 }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Smart Pointers
|
|
97
|
+
```rust
|
|
98
|
+
// Box: Heap allocation, single ownership
|
|
99
|
+
let boxed: Box<dyn Trait> = Box::new(implementation);
|
|
100
|
+
|
|
101
|
+
// Rc: Shared ownership (single-threaded)
|
|
102
|
+
let shared = Rc::new(data);
|
|
103
|
+
let clone = Rc::clone(&shared);
|
|
104
|
+
|
|
105
|
+
// Arc: Shared ownership (thread-safe)
|
|
106
|
+
let shared = Arc::new(data);
|
|
107
|
+
let clone = Arc::clone(&shared);
|
|
108
|
+
|
|
109
|
+
// Interior mutability
|
|
110
|
+
let cell = RefCell::new(data);
|
|
111
|
+
let mut borrowed = cell.borrow_mut();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Error Handling
|
|
115
|
+
|
|
116
|
+
### Result Pattern
|
|
117
|
+
```rust
|
|
118
|
+
#[derive(Debug, thiserror::Error)]
|
|
119
|
+
pub enum AppError {
|
|
120
|
+
#[error("IO error: {0}")]
|
|
121
|
+
Io(#[from] std::io::Error),
|
|
122
|
+
|
|
123
|
+
#[error("Parse error: {0}")]
|
|
124
|
+
Parse(#[from] serde_json::Error),
|
|
125
|
+
|
|
126
|
+
#[error("Not found: {0}")]
|
|
127
|
+
NotFound(String),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fn read_config(path: &Path) -> Result<Config, AppError> {
|
|
131
|
+
let content = std::fs::read_to_string(path)?;
|
|
132
|
+
let config: Config = serde_json::from_str(&content)?;
|
|
133
|
+
Ok(config)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Option Combinators
|
|
138
|
+
```rust
|
|
139
|
+
// Chain Option operations
|
|
140
|
+
fn get_user_email(id: UserId) -> Option<String> {
|
|
141
|
+
get_user(id)
|
|
142
|
+
.and_then(|user| user.email)
|
|
143
|
+
.filter(|email| email.contains('@'))
|
|
144
|
+
.map(|email| email.to_lowercase())
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Use ? with Option in Option-returning functions
|
|
148
|
+
fn parse_config(text: &str) -> Option<Config> {
|
|
149
|
+
let first_line = text.lines().next()?;
|
|
150
|
+
let parts: Vec<_> = first_line.split('=').collect();
|
|
151
|
+
let key = parts.get(0)?;
|
|
152
|
+
let value = parts.get(1)?;
|
|
153
|
+
Some(Config::new(key, value))
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Async Rust
|
|
158
|
+
|
|
159
|
+
### Basic Async
|
|
160
|
+
```rust
|
|
161
|
+
use tokio::time::{sleep, Duration};
|
|
162
|
+
|
|
163
|
+
async fn fetch_data(url: &str) -> Result<Data, Error> {
|
|
164
|
+
let response = reqwest::get(url).await?;
|
|
165
|
+
let data = response.json().await?;
|
|
166
|
+
Ok(data)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async fn process_with_timeout(data: &Data) -> Result<Output, Error> {
|
|
170
|
+
tokio::time::timeout(
|
|
171
|
+
Duration::from_secs(30),
|
|
172
|
+
heavy_computation(data)
|
|
173
|
+
).await?
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Async Trait (with async-trait crate)
|
|
178
|
+
```rust
|
|
179
|
+
use async_trait::async_trait;
|
|
180
|
+
|
|
181
|
+
#[async_trait]
|
|
182
|
+
trait Repository {
|
|
183
|
+
async fn find(&self, id: Id) -> Result<Entity, Error>;
|
|
184
|
+
async fn save(&self, entity: &Entity) -> Result<(), Error>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
#[async_trait]
|
|
188
|
+
impl Repository for PostgresRepo {
|
|
189
|
+
async fn find(&self, id: Id) -> Result<Entity, Error> {
|
|
190
|
+
sqlx::query_as!(Entity, "SELECT * FROM entities WHERE id = $1", id)
|
|
191
|
+
.fetch_one(&self.pool)
|
|
192
|
+
.await
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async fn save(&self, entity: &Entity) -> Result<(), Error> {
|
|
196
|
+
// ...
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Concurrent Operations
|
|
202
|
+
```rust
|
|
203
|
+
use futures::future::join_all;
|
|
204
|
+
|
|
205
|
+
async fn fetch_all(urls: Vec<String>) -> Vec<Result<Data, Error>> {
|
|
206
|
+
let futures: Vec<_> = urls.iter()
|
|
207
|
+
.map(|url| fetch_data(url))
|
|
208
|
+
.collect();
|
|
209
|
+
|
|
210
|
+
join_all(futures).await
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Project Structure
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
my_crate/
|
|
218
|
+
├── Cargo.toml
|
|
219
|
+
├── src/
|
|
220
|
+
│ ├── lib.rs # Library root
|
|
221
|
+
│ ├── main.rs # Binary (optional)
|
|
222
|
+
│ ├── error.rs
|
|
223
|
+
│ ├── config.rs
|
|
224
|
+
│ └── module/
|
|
225
|
+
│ ├── mod.rs
|
|
226
|
+
│ └── submodule.rs
|
|
227
|
+
├── tests/
|
|
228
|
+
│ └── integration.rs
|
|
229
|
+
├── benches/
|
|
230
|
+
│ └── benchmarks.rs
|
|
231
|
+
└── examples/
|
|
232
|
+
└── example.rs
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Cargo.toml
|
|
236
|
+
```toml
|
|
237
|
+
[package]
|
|
238
|
+
name = "my-crate"
|
|
239
|
+
version = "0.1.0"
|
|
240
|
+
edition = "2021"
|
|
241
|
+
|
|
242
|
+
[dependencies]
|
|
243
|
+
tokio = { version = "1", features = ["full"] }
|
|
244
|
+
serde = { version = "1", features = ["derive"] }
|
|
245
|
+
thiserror = "1"
|
|
246
|
+
anyhow = "1"
|
|
247
|
+
|
|
248
|
+
[dev-dependencies]
|
|
249
|
+
criterion = { version = "0.5", features = ["html_reports"] }
|
|
250
|
+
|
|
251
|
+
[[bench]]
|
|
252
|
+
name = "benchmarks"
|
|
253
|
+
harness = false
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Unsafe Rust Guidelines
|
|
257
|
+
|
|
258
|
+
### When to Use Unsafe
|
|
259
|
+
```rust
|
|
260
|
+
// 1. FFI bindings
|
|
261
|
+
extern "C" {
|
|
262
|
+
fn external_function(ptr: *const u8, len: usize);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 2. Performance-critical code with verified invariants
|
|
266
|
+
unsafe fn unchecked_get(slice: &[u8], index: usize) -> u8 {
|
|
267
|
+
debug_assert!(index < slice.len());
|
|
268
|
+
*slice.get_unchecked(index)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 3. Implementing low-level abstractions
|
|
272
|
+
pub struct MyVec<T> {
|
|
273
|
+
ptr: NonNull<T>,
|
|
274
|
+
len: usize,
|
|
275
|
+
cap: usize,
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Unsafe Guidelines
|
|
280
|
+
- Minimize unsafe blocks
|
|
281
|
+
- Document safety invariants
|
|
282
|
+
- Use debug_assert! for invariants
|
|
283
|
+
- Wrap unsafe in safe abstractions
|
|
284
|
+
- Test thoroughly with Miri
|
|
285
|
+
|
|
286
|
+
## Anti-Patterns to Avoid
|
|
287
|
+
|
|
288
|
+
| Anti-Pattern | Why Bad | Better Approach |
|
|
289
|
+
|--------------|---------|-----------------|
|
|
290
|
+
| `.unwrap()` everywhere | Panics in prod | Use `?` or handle errors |
|
|
291
|
+
| `Rc<RefCell<T>>` overuse | Runtime overhead | Consider redesign |
|
|
292
|
+
| Unnecessary `clone()` | Performance cost | Borrow when possible |
|
|
293
|
+
| Fighting the borrow checker | Usually wrong design | Redesign data flow |
|
|
294
|
+
| Large unsafe blocks | Hard to verify | Minimize, document |
|
|
295
|
+
|
|
296
|
+
## Constraints
|
|
297
|
+
|
|
298
|
+
- Avoid `.unwrap()` in library code
|
|
299
|
+
- Minimize `unsafe` usage
|
|
300
|
+
- Document all safety invariants
|
|
301
|
+
- Use `clippy` lints
|
|
302
|
+
- Run `miri` for unsafe code testing
|
|
303
|
+
- Benchmark before optimizing
|
|
304
|
+
|
|
305
|
+
## Related Skills
|
|
306
|
+
|
|
307
|
+
- `backend-developer` - Rust web services
|
|
308
|
+
- `security-engineer` - Memory-safe systems
|
|
309
|
+
- `performance-engineer` - Low-level optimization
|