agentleFS
Sign inSign up

subcog

zircote/subcog/.github/copilot-instructions.md

This document provides context for GitHub Copilot when working with this Rust project. This is a Rust crate using modern tooling: - Rust: 1.80+ (2024 edition) - Build System: Cargo - Linting: clippy with pedantic and nursery lints - Formatting: rustfmt - Testing: Built-in test framework + proptest - Supply Chain Security: cargo-deny Use Result types instead of panicking: Use thiserror for custom error types: Provide explicit return types for public functions: Use doc comments with examples: rust /// use…

Copilot instructions28 starsChanged 7 months ago
# GitHub Copilot Instructions

This document provides context for GitHub Copilot when working with this Rust project.

## Project Context

This is a Rust crate using modern tooling:
- **Rust**: 1.80+ (2024 edition)
- **Build System**: Cargo
- **Linting**: clippy with pedantic and nursery lints
- **Formatting**: rustfmt
- **Testing**: Built-in test framework + proptest
- **Supply Chain Security**: cargo-deny

## Code Generation Guidelines

### Error Handling

Use `Result` types instead of panicking:

```rust
// Good - Returns Result
pub fn parse_value(input: &str) -> Result<i64, ParseError> {
    input.parse().map_err(|e| ParseError::InvalidFormat(e))
}

// Avoid - Panics on failure
pub fn parse_value(input: &str) -> i64 {
    input.parse().unwrap() // Never do this
}
```

Use `thiserror` for custom error types:

```rust
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("invalid input: {0}")]
    InvalidInput(String),

    #[error("operation failed: {operation}")]
    OperationFailed { operation: String },

    #[error(transparent)]
    Io(#[from] std::io::Error),
}
```

### Type Annotations

Provide explicit return types for public functions:

```rust
// Good - explicit return type
pub fn process_data(items: &[String]) -> Vec<ProcessedItem> {
    // implementation
}

// Avoid for public APIs
pub fn process_data(items: &[String]) -> impl Iterator<Item = ProcessedItem> {
    // implementation
}
```

### Documentation

Use doc comments with examples:

```rust
/// Processes a list of items according to the given configuration.
///
/// # Arguments
///
/// * `items` - The items to process.
/// * `config` - Configuration options for processing.
///
/// # Returns
///
/// A vector of processed items.
///
/// # Errors
///
/// Returns [`Error::InvalidInput`] if any item is invalid.
///
/// # Examples
///
/// ```rust
/// use {{crate_name}}::{process, Config};
///
/// let items = vec!["a", "b", "c"];
/// let config = Config::default();
/// let result = process(&items, &config)?;
/// # Ok::<(), {{crate_name}}::Error>(())
/// ```
pub fn process(items: &[&str], config: &Config) -> Result<Vec<Item>> {
    // implementation
}
```

### Ownership and Borrowing

Prefer borrowing over ownership when possible:

```rust
// Good - borrows the slice
pub fn sum_values(values: &[i64]) -> i64 {
    values.iter().sum()
}

// Avoid - takes ownership unnecessarily
pub fn sum_values(values: Vec<i64>) -> i64 {
    values.iter().sum()
}
```

Use `Cow` for efficient string handling:

```rust
use std::borrow::Cow;

pub fn normalize_name(name: &str) -> Cow<'_, str> {
    if name.contains(' ') {
        Cow::Owned(name.replace(' ', "_"))
    } else {
        Cow::Borrowed(name)
    }
}
```

### Structs and Enums

Use builder pattern for complex structs:

```rust
#[derive(Debug, Clone, Default)]
pub struct Config {
    pub timeout: Duration,
    pub retries: u32,
    pub verbose: bool,
}

impl Config {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    #[must_use]
    pub fn with_timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

    #[must_use]
    pub fn with_retries(mut self, retries: u32) -> Self {
        self.retries = retries;
        self
    }
}
```

### Testing

Write comprehensive unit tests:

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add_positive_numbers() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    fn test_divide_by_zero_returns_error() {
        let result = divide(10, 0);
        assert!(matches!(result, Err(Error::DivisionByZero)));
    }
}
```

Use proptest for property-based testing:

```rust
use proptest::prelude::*;

proptest! {
    #[test]
    fn add_is_commutative(a in any::<i64>(), b in any::<i64>()) {
        prop_assert_eq!(add(a, b), add(b, a));
    }
}
```

### Async Code

Use async/await with tokio:

```rust
pub async fn fetch_data(url: &str) -> Result<Data> {
    let response = reqwest::get(url).await?;
    let data = response.json().await?;
    Ok(data)
}
```

## Common Patterns

### Iterator Chains

```rust
let result: Vec<_> = items
    .iter()
    .filter(|item| item.is_valid())
    .map(|item| item.transform())
    .collect();
```

### Option and Result Combinators

```rust
// Option chaining
let value = config
    .get_setting("key")
    .and_then(|s| s.parse().ok())
    .unwrap_or_default();

// Result chaining with ?
fn process() -> Result<Output> {
    let data = load_data()?;
    let parsed = parse_data(&data)?;
    let result = transform(parsed)?;
    Ok(result)
}
```

### Const Functions

Prefer `const fn` for compile-time evaluation:

```rust
#[must_use]
pub const fn new() -> Self {
    Self { value: 0 }
}
```

## File Locations

- Source code: `src/`
- Library entry: `src/lib.rs`
- Binary entry: `src/main.rs`
- Integration tests: `tests/`
- Benchmarks: `benches/` (with criterion)

## Commands

```bash
cargo build           # Build
cargo test            # Run tests
cargo clippy          # Lint
cargo fmt             # Format
cargo doc --open      # Generate and view docs
cargo deny check      # Check supply chain
```

Discussion

Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.

Posts are public.Sign in to post

No one has posted yet. Be the first.