Skip to main content

lighty_modsloader/
request.rs

1// Copyright (c) 2025 Hamadi
2// Licensed under the MIT License
3
4//! User-facing types for the mod resolver.
5
6/// A mod the user asked the launcher to install.
7///
8/// `version` / `file_id` are optional pins — if absent, the resolver picks
9/// the latest release compatible with the instance's MC version + loader.
10#[derive(Debug, Clone)]
11pub enum ModRequest {
12    Modrinth {
13        id_or_slug: String,
14        version: Option<String>,
15    },
16    CurseForge {
17        mod_id: u32,
18        file_id: Option<u32>,
19    },
20}
21
22/// Source tag — used for dedup keys and error messages.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub enum ModSource {
25    Modrinth,
26    CurseForge,
27}
28
29impl ModSource {
30    pub fn as_str(self) -> &'static str {
31        match self {
32            ModSource::Modrinth => "modrinth",
33            ModSource::CurseForge => "curseforge",
34        }
35    }
36}
37
38/// Dedup key for the BFS resolver: `(source, project-level identifier)`.
39/// Version-agnostic — first occurrence wins (BFS order, user requests
40/// before transitively-pulled deps).
41#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub struct ModKey {
43    pub source: ModSource,
44    pub id: String,
45}
46
47impl ModKey {
48    pub fn modrinth(id: impl Into<String>) -> Self {
49        Self { source: ModSource::Modrinth, id: id.into() }
50    }
51    pub fn curseforge(mod_id: u32) -> Self {
52        Self { source: ModSource::CurseForge, id: mod_id.to_string() }
53    }
54}
55
56impl From<&ModRequest> for ModKey {
57    fn from(req: &ModRequest) -> Self {
58        match req {
59            ModRequest::Modrinth { id_or_slug, .. } => ModKey::modrinth(id_or_slug.clone()),
60            ModRequest::CurseForge { mod_id, .. } => ModKey::curseforge(*mod_id),
61        }
62    }
63}