use std::path::PathBuf; use thiserror::Error; use async_trait::async_trait; use crate::song::Song; #[derive(Debug, Clone)] pub enum TabSource { File(PathBuf), Url(String), } #[derive(Debug, Error)] pub enum FetchError { #[error("IO error: {0}")] Io(#[from] std::io::Error), #[error("Network error: {0}")] Network(String), #[error("Response is not HTML")] InvalidContentType, } #[derive(Debug, Error)] pub enum ParseError { #[error("Tab content not found in HTML")] MissingContent, #[error("Malformed HTML: {0}")] MalformedHtml(String), } #[async_trait] pub trait TabFetcherPort: Send + Sync { async fn fetch(&self, source: TabSource) -> Result; } pub trait TabParserPort: Send + Sync { fn parse(&self, html: &str) -> Result; }