Skip to main content
Glama
rust-validation.js4.72 kB
/** * Validation utilities for Rust code analysis */ const MAX_CODE_SIZE = 100 * 1024; // 100KB limit /** * Validates Rust code input * @param {string} code - The Rust code to validate * @returns {Object} Validation result with valid flag and error if invalid */ export function validateRustCode(code) { if (typeof code !== 'string') { return { valid: false, error: { content: [{ type: 'text', text: '❌ Error: Code must be a string.', }], }, }; } if (code.length === 0) { return { valid: false, error: { content: [{ type: 'text', text: '❌ Error: Code cannot be empty.', }], }, }; } if (code.length > MAX_CODE_SIZE) { return { valid: false, error: { content: [{ type: 'text', text: `❌ Error: Code exceeds maximum size of ${MAX_CODE_SIZE / 1024}KB.`, }], }, }; } return { valid: true }; } /** * Sanitizes Rust filename * @param {string} filename - The filename to sanitize * @returns {string} Sanitized filename */ export function sanitizeRustFilename(filename) { if (!filename || typeof filename !== 'string') { return 'code.rs'; } // Remove any path components and keep only the filename const baseName = filename.split(/[/\\]/).pop(); // Ensure it has a Rust extension if (!baseName.match(/\.(rs|toml)$/i)) { return baseName + '.rs'; } return baseName; } /** * Detects Rust edition from code or defaults * @param {string} code - The Rust code * @returns {string} Edition year */ export function detectRustEdition(code) { // Check for edition attribute in code const editionMatch = code.match(/#!\[.*edition\s*=\s*"(\d{4})".*\]/); if (editionMatch) { return editionMatch[1]; } // Default to 2021 edition return '2021'; } /** * Validates Rust tool options * @param {Object} options - Tool options to validate * @returns {Object} Validated options with defaults */ export function validateRustToolOptions(options) { const validated = { edition: '2021', level: 'warn', target: null, features: [], ...options }; // Validate edition const validEditions = ['2015', '2018', '2021', '2024']; if (!validEditions.includes(validated.edition)) { validated.edition = '2021'; } // Validate lint level const validLevels = ['allow', 'warn', 'deny', 'forbid']; if (!validLevels.includes(validated.level)) { validated.level = 'warn'; } // Ensure features is an array if (!Array.isArray(validated.features)) { validated.features = []; } return validated; } /** * Maps Rust severity levels to MCP severity * @param {string} rustLevel - Rust lint level * @returns {string} MCP severity level */ export function mapRustSeverity(rustLevel) { const severityMap = { 'error': 'error', 'warning': 'warning', 'note': 'info', 'help': 'info', 'failure-note': 'error' }; return severityMap[rustLevel.toLowerCase()] || 'warning'; } /** * Extracts crate dependencies from Rust code * @param {string} code - The Rust code * @returns {Array<string>} List of external crate dependencies */ export function extractCrateDependencies(code) { const dependencies = new Set(); // Match extern crate declarations const externCrates = code.matchAll(/extern\s+crate\s+(\w+);/g); for (const match of externCrates) { dependencies.add(match[1]); } // Match use statements for external crates const useStatements = code.matchAll(/use\s+(\w+)(::|;)/g); for (const match of useStatements) { const crate = match[1]; // Filter out std library modules if (!['std', 'core', 'alloc', 'proc_macro', 'test'].includes(crate)) { dependencies.add(crate); } } return Array.from(dependencies); } /** * Checks if code contains unsafe blocks * @param {string} code - The Rust code * @returns {boolean} True if unsafe blocks are present */ export function hasUnsafeCode(code) { return /\bunsafe\s*\{/.test(code); } /** * Gets Rust file type from extension * @param {string} filename - The filename * @returns {string} File type (lib, bin, test, bench, build) */ export function getRustFileType(filename) { if (!filename) return 'lib'; const name = filename.toLowerCase(); if (name === 'build.rs') return 'build'; if (name === 'main.rs') return 'bin'; if (name === 'lib.rs') return 'lib'; if (name.includes('test') || name.includes('_test.rs')) return 'test'; if (name.includes('bench') || name.includes('_bench.rs')) return 'bench'; if (name === 'cargo.toml') return 'manifest'; return 'lib'; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/moikas-code/moidvk'

If you have feedback or need assistance with the MCP directory API, please join our Discord server