1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::path::PathBuf;
4
5use crate::{Language, Span};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case")]
9pub enum ChunkKind {
10 Function,
11 Method,
12 Struct,
13 Enum,
14 Trait,
15 Impl,
16 Module,
17 Class,
18 File,
19}
20
21impl ChunkKind {
22 pub fn from_name(name: &str) -> Option<Self> {
25 Some(match name.to_lowercase().as_str() {
26 "function" | "fn" | "func" => Self::Function,
27 "method" => Self::Method,
28 "struct" => Self::Struct,
29 "enum" => Self::Enum,
30 "trait" => Self::Trait,
31 "impl" => Self::Impl,
32 "module" | "mod" => Self::Module,
33 "class" => Self::Class,
34 "file" => Self::File,
35 _ => return None,
36 })
37 }
38
39 pub const ALL: &'static [Self] = &[
41 Self::Function,
42 Self::Method,
43 Self::Struct,
44 Self::Enum,
45 Self::Trait,
46 Self::Impl,
47 Self::Module,
48 Self::Class,
49 Self::File,
50 ];
51}
52
53impl fmt::Display for ChunkKind {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 let s = match self {
56 Self::Function => "function",
57 Self::Method => "method",
58 Self::Struct => "struct",
59 Self::Enum => "enum",
60 Self::Trait => "trait",
61 Self::Impl => "impl",
62 Self::Module => "module",
63 Self::Class => "class",
64 Self::File => "file",
65 };
66 f.write_str(s)
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct Chunk {
72 pub id: String,
74 pub path: PathBuf,
76 pub language: Language,
78 pub kind: ChunkKind,
80 pub name: Option<String>,
82 pub content: String,
84 pub span: Span,
86 pub doc: Option<String>,
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn every_kind_parses_back_from_its_own_name() {
96 for kind in ChunkKind::ALL {
97 assert_eq!(
98 ChunkKind::from_name(&kind.to_string()),
99 Some(*kind),
100 "{kind} does not round-trip through from_name"
101 );
102 }
103 }
104
105 #[test]
106 fn kind_names_are_case_insensitive_and_accept_short_forms() {
107 assert_eq!(ChunkKind::from_name("FN"), Some(ChunkKind::Function));
108 assert_eq!(ChunkKind::from_name("Mod"), Some(ChunkKind::Module));
109 assert_eq!(ChunkKind::from_name("nope"), None);
110 }
111}