sub-converter

Crates.iosub-converter
lib.rssub-converter
version0.1.5
created_at2025-10-10 07:25:09.172266+00
updated_at2025-10-12 05:46:44.388194+00
descriptionA sub converter library
homepage
repository
max_upload_size
id1876614
size62,886
(themanforfree)

documentation

README

sub-converter (library)

Core library for converting subscription inputs (Clash YAML, SingBox JSON, and URI lists like ss://, trojan://) into Clash or SingBox configurations with optional templates.

Public API (stable surface)

  • Types
    • InputFormat, OutputFormat, InputItem
    • template::Template (Template::Clash(ClashConfig), Template::SingBox(SingBoxConfig))
    • formats::{ClashConfig, SingBoxConfig}
    • Error, Result
  • Functions
    • detect_format(content: &str) -> Result<InputFormat>
    • convert(inputs: Vec<InputItem>, template: Template) -> Result<String>

Internal modules (parsing, emitting, IR) are intentionally not exposed to avoid abstraction leakage.

Quick start

use sub_converter::{InputItem, InputFormat, OutputFormat, convert, detect_format};
use sub_converter::template::Template;
use sub_converter::formats::{ClashConfig, SingBoxConfig};

fn main() -> Result<(), sub_converter::Error> {
    let content = "ss://YWVzLTI1Ni1nY206cGFzcw@a.com:123#A\n\
                   trojan://pwd@b.com:443#B";

    let fmt = detect_format(content)?; // or specify manually
    let inputs = vec![InputItem { format: fmt, content: content.into() }];

    // Clash output
    let clash = convert(inputs.clone(), Template::Clash(ClashConfig::default()))?;

    // SingBox output
    let singbox = convert(inputs, Template::SingBox(SingBoxConfig::default()))?;

    println!("{}\n{}", clash, singbox);
    Ok(())
}

Multiple inputs and merging

convert accepts multiple InputItems (mixed formats). Items are parsed then merged in order.

let inputs = vec![
    InputItem { format: InputFormat::Clash, content: clash_yaml.into() },
    InputItem { format: InputFormat::SingBox, content: singbox_json.into() },
    InputItem { format: InputFormat::UriList, content: uri_list.into() },
];
let out = convert(inputs, Template::Clash(ClashConfig::default()))?;

Templates

Use defaults via ClashConfig::default() / SingBoxConfig::default(), or build from serde:

let tpl_yaml: &str = include_str!("../../templates/clash-example.yaml");
let clash_tpl: ClashConfig = serde_yaml::from_str(tpl_yaml)?;
let out = convert(inputs, Template::Clash(clash_tpl))?;

Error handling

All operations return Result<T, Error>, covering validation, parsing, emitting, and template errors.

Design

  • Minimal, stable façade: high-level detect_format + convert
  • Strong typing for templates via ClashConfig / SingBoxConfig
  • Internals remain private to prevent coupling
Commit count: 0

cargo fmt