Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tomevault-io/skills-registry --skill rust-design-patterns명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | rust-design-patterns |
| description | | Use when this capability is needed. |
Collection of idiomatic patterns, architectural choices, and best practices for Rust.
#[derive(Default)]
struct Config {
timeout: u64,
retries: u32,
}
impl Default for Config {
fn default() -> Self {
Self {
timeout: 30,
retries: 3,
}
}
}
// Usage
let config = Config::default();
let config = Config { retries: 5, ..Default::default() };
impl User {
// Primary constructor
pub fn new(name: String, email: String) -> Self {
Self { id: Uuid::new_v4(), name, email, created_at: Utc::now() }
}
// Alternative constructors
pub fn anonymous() -> Self {
Self::new("Anonymous".into(), "anonymous@example.com".into())
}
// Fallible constructor
pub fn try_new(name: &str, email: &str) -> Result<Self, ValidationError> {
validate_email(email)?;
Ok(Self::new(name.into(), email.into()))
}
}
// Destructure what you need
let Point { x, y: _ } = point; // Ignore y
let Point { x, .. } = point; // Ignore rest
// Match with guards
match result {
Ok(value) if value > 0 => handle_positive(value),
Ok(_) => handle_zero_or_negative(),
Err(e) => handle_error(e),
}
For complex object construction:
pub struct ServerConfig {
host: String,
port: u16,
workers: usize,
tls: Option<TlsConfig>,
}
#[derive(Default)]
pub struct ServerConfigBuilder {
host: Option<String>,
port: Option<u16>,
workers: Option<usize>,
tls: Option<TlsConfig>,
}
impl ServerConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn host(mut self, host: impl Into<String>) -> Self {
self.host = Some(host.into());
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
( , workers: ) {
.workers = (workers);
}
( , tls: TlsConfig) {
.tls = (tls);
}
() <ServerConfig, BuildError> {
(ServerConfig {
host: .host.(|| .()),
port: .port.(BuildError::MissingPort)?,
workers: .workers.(num_cpus::()),
tls: .tls,
})
}
}
= ServerConfigBuilder::()
.()
.()
.()
.()?;
Compile-time enforcement of required fields:
// Marker types
struct NoHost;
struct HasHost(String);
struct NoPort;
struct HasPort(u16);
struct Builder<H, P> {
host: H,
port: P,
workers: usize,
}
impl Builder<NoHost, NoPort> {
pub fn new() -> Self {
Self { host: NoHost, port: NoPort, workers: 4 }
}
}
impl<P> Builder<NoHost, P> {
pub fn host(self, host: impl Into<String>) -> Builder<HasHost, P> {
Builder {
host: HasHost(host.into()),
port: self.port,
workers: self.workers,
}
}
}
impl<H> Builder<H, NoPort> {
pub fn port(self, port: u16) -> Builder<H, HasPort> {
Builder {
host: self.host,
port: HasPort(port),
workers: self.workers,
}
}
}
// build() only available when both host and port are set
<HasHost, HasPort> {
() Server {
Server {
host: .host.,
port: .port.,
workers: .workers,
}
}
}
= Builder::()
.()
.()
.();
Type safety through wrapper types:
// Distinct types from primitives
struct UserId(u64);
struct OrderId(u64);
// Can't accidentally swap them
fn get_user_orders(user_id: UserId) -> Vec<OrderId> { ... }
// With validation
pub struct Email(String);
impl Email {
pub fn new(s: impl AsRef<str>) -> Result<Self, EmailError> {
let s = s.as_ref();
if Self::is_valid(s) {
Ok(Self(s.to_string()))
} else {
Err(EmailError::Invalid)
}
}
fn is_valid(s: &str) -> bool {
s.contains('@') && s.contains('.')
}
pub fn as_str(&) & {
&.
}
}
std::ops::Deref;
{
= ;
(&) & { &. }
}
Add methods to external types:
pub trait StringExt {
fn is_blank(&self) -> bool;
fn truncate_with_ellipsis(&self, max_len: usize) -> String;
}
impl StringExt for str {
fn is_blank(&self) -> bool {
self.trim().is_empty()
}
fn truncate_with_ellipsis(&self, max_len: usize) -> String {
if self.len() <= max_len {
self.to_string()
} else {
format!("{}...", &self[..max_len.saturating_sub(3)])
}
}
}
// Usage
" ".is_blank(); // true
"Hello World".truncate_with_ellipsis(8); // "Hello..."
Automatic cleanup via Drop:
pub struct TempFile {
path: PathBuf,
}
impl TempFile {
pub fn new(name: &str) -> std::io::Result<Self> {
let path = std::env::temp_dir().join(name);
std::fs::File::create(&path)?;
Ok(Self { path })
}
pub fn path(&self) -> &Path {
&self.path
}
}
impl Drop for TempFile {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.path);
}
}
// File automatically deleted when TempFile goes out of scope
{
let temp = TempFile::new("data.tmp")?;
write_data(temp.path())?;
} // File deleted here
Simplify complex subsystems:
pub struct Database {
pool: ConnectionPool,
cache: Cache,
metrics: Metrics,
}
impl Database {
pub fn new(config: &Config) -> Result<Self, DbError> {
Ok(Self {
pool: ConnectionPool::new(&config.db_url)?,
cache: Cache::new(config.cache_size),
metrics: Metrics::new(),
})
}
// Simple interface hides complexity
pub async fn get_user(&self, id: UserId) -> Result<User, DbError> {
// Check cache first
if let Some(user) = self.cache.get(&id) {
self.metrics.record_cache_hit();
return Ok(user);
}
// Query database
let conn = self.pool.get().await?;
let user = conn.query_one("SELECT * FROM users WHERE id = $1", &[&id]).await?;
.cache.(id, user.());
.metrics.();
(user)
}
}
pub enum ConnectionState {
Disconnected,
Connecting { attempt: u32, started_at: Instant },
Connected { session: Session },
Disconnecting,
}
pub struct Connection {
state: ConnectionState,
config: Config,
}
impl Connection {
pub fn connect(&mut self) -> Result<(), ConnectionError> {
self.state = match std::mem::take(&mut self.state) {
ConnectionState::Disconnected => {
ConnectionState::Connecting {
attempt: 1,
started_at: Instant::now(),
}
}
other => return Err(ConnectionError::InvalidState),
};
Ok(())
}
pub fn on_connected(&mut self, session: Session) {
if matches!(self.state, ConnectionState::Connecting { .. }) {
self.state = ConnectionState::Connected { session };
}
}
pub fn is_connected(&self) -> bool {
matches!(self.state, ConnectionState::Connected { .. })
}
}
impl Default {
() {
::Disconnected
}
}
Encode states in the type system:
// State types
struct Draft;
struct Published;
struct Archived;
struct Post<State> {
content: String,
_state: std::marker::PhantomData<State>,
}
impl Post<Draft> {
pub fn new(content: String) -> Self {
Self { content, _state: PhantomData }
}
pub fn edit(&mut self, content: String) {
self.content = content;
}
pub fn publish(self) -> Post<Published> {
Post { content: self.content, _state: PhantomData }
}
}
impl Post<Published> {
pub fn archive(self) -> Post<Archived> {
Post { content: self.content, _state: PhantomData }
}
// Can't edit published posts!
}
// Compile-time state enforcement
let post = Post::new("Hello".into());
post.edit(.());
= post.();
trait Compressor {
fn compress(&self, data: &[u8]) -> Vec<u8>;
fn decompress(&self, data: &[u8]) -> Vec<u8>;
}
struct GzipCompressor;
struct LzmaCompressor;
impl Compressor for GzipCompressor {
fn compress(&self, data: &[u8]) -> Vec<u8> { /* ... */ }
fn decompress(&self, data: &[u8]) -> Vec<u8> { /* ... */ }
}
impl Compressor for LzmaCompressor {
fn compress(&self, data: &[u8]) -> Vec<u8> { /* ... */ }
fn decompress(&self, data: &[]) <> { }
}
<C: Compressor> {
compressor: C,
}
<C: Compressor> FileProcessor<C> {
(compressor: C) {
{ compressor }
}
(&, data: &[]) <> {
.compressor.(data)
}
}
= FileProcessor::(GzipCompressor);
= processor.(&data);
trait Command {
fn execute(&self);
fn undo(&self);
}
struct InsertText {
position: usize,
text: String,
}
impl Command for InsertText {
fn execute(&self) {
// Insert text at position
}
fn undo(&self) {
// Remove text from position
}
}
struct CommandHistory {
commands: Vec<Box<dyn Command>>,
current: usize,
}
impl CommandHistory {
pub fn execute(&mut self, cmd: Box<dyn Command>) {
cmd.execute();
self.commands.truncate(self.current);
self.commands.push(cmd);
self.current += 1;
}
pub fn undo(&mut ) {
.current > {
.current -= ;
.commands[.current].();
}
}
(& ) {
.current < .commands.() {
.commands[.current].();
.current += ;
}
}
}
// Bad: One type does everything
struct App {
users: Vec<User>,
orders: Vec<Order>,
products: Vec<Product>,
// ... 50 more fields
fn do_everything(&mut self) { ... }
}
// Good: Separate concerns
struct UserService { ... }
struct OrderService { ... }
struct ProductService { ... }
struct App {
users: UserService,
orders: OrderService,
products: ProductService,
}
// Bad: String for everything
fn set_status(status: &str) {
match status {
"pending" | "active" | "done" => { ... }
_ => panic!("Invalid status"),
}
}
// Good: Use enums
enum Status { Pending, Active, Done }
fn set_status(status: Status) {
match status {
Status::Pending => { ... }
Status::Active => { ... }
Status::Done => { ... }
}
}
// Bad: Using Deref for inheritance
struct Dog {
animal: Animal,
}
impl Deref for Dog {
type Target = Animal;
fn deref(&self) -> &Animal { &self.animal }
}
// Good: Use traits
trait Animal {
fn speak(&self);
}
impl Animal for Dog {
fn speak(&self) { println!("Woof!"); }
}
| Need | Pattern |
|---|---|
| Complex construction | Builder |
| Compile-time construction validation | Typestate Builder |
| Type safety for primitives | Newtype |
| Add methods to foreign types | Extension Trait |
| Automatic cleanup | RAII Guard |
| Multiple states with transitions | State Machine |
| Compile-time state validation | Typestate |
| Swappable algorithms | Strategy |
| Undoable operations | Command |
Drop.Source: adxptived/Rust-Skills — distributed by TomeVault.