use serde::{Deserialize, Serialize};
use std::fmt;
use std::path::PathBuf;
use crate::{Language, Span};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ChunkKind {
Function,
Method,
Struct,
Enum,
Trait,
Impl,
Module,
Class,
File,
}
impl ChunkKind {
pub fn from_name(name: &str) -> Option<Self> {
Some(match name.to_lowercase().as_str() {
"function" | "fn" | "func" => Self::Function,
"method" => Self::Method,
"struct" => Self::Struct,
"enum" => Self::Enum,
"trait" => Self::Trait,
"impl" => Self::Impl,
"module" | "mod" => Self::Module,
"class" => Self::Class,
"file" => Self::File,
_ => return None,
})
}
pub const ALL: &'static [Self] = &[
Self::Function,
Self::Method,
Self::Struct,
Self::Enum,
Self::Trait,
Self::Impl,
Self::Module,
Self::Class,
Self::File,
];
}
impl fmt::Display for ChunkKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::Function => "function",
Self::Method => "method",
Self::Struct => "struct",
Self::Enum => "enum",
Self::Trait => "trait",
Self::Impl => "impl",
Self::Module => "module",
Self::Class => "class",
Self::File => "file",
};
f.write_str(s)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Chunk {
pub id: String,
pub path: PathBuf,
pub language: Language,
pub kind: ChunkKind,
pub name: Option<String>,
pub content: String,
pub span: Span,
pub doc: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_kind_parses_back_from_its_own_name() {
for kind in ChunkKind::ALL {
assert_eq!(
ChunkKind::from_name(&kind.to_string()),
Some(*kind),
"{kind} does not round-trip through from_name"
);
}
}
#[test]
fn kind_names_are_case_insensitive_and_accept_short_forms() {
assert_eq!(ChunkKind::from_name("FN"), Some(ChunkKind::Function));
assert_eq!(ChunkKind::from_name("Mod"), Some(ChunkKind::Module));
assert_eq!(ChunkKind::from_name("nope"), None);
}
}