lingora_core/audit/
workspace.rs1use std::collections::HashSet;
2
3use crate::{
4 domain::{LanguageRoot, Locale},
5 fluent::FluentFile,
6 rust::RustFile,
7};
8
9#[derive(Clone, Debug)]
17pub struct Workspace {
18 fluent_files: Vec<FluentFile>,
19 canonical: Locale,
20 primaries: Vec<Locale>,
21 rust_files: Vec<RustFile>,
22}
23
24impl Workspace {
25 pub fn new(
27 fluent_files: Vec<FluentFile>,
28 canonical: Locale,
29 primaries: Vec<Locale>,
30 rust_files: Vec<RustFile>,
31 ) -> Self {
32 Self {
33 fluent_files,
34 canonical,
35 primaries,
36 rust_files,
37 }
38 }
39
40 pub fn fluent_files(&self) -> &[FluentFile] {
42 &self.fluent_files
43 }
44
45 pub fn locales(&self) -> impl Iterator<Item = &Locale> {
47 self.fluent_files
48 .iter()
49 .map(|f| f.locale())
50 .collect::<HashSet<_>>()
51 .into_iter()
52 }
53
54 pub fn language_roots(&self) -> impl Iterator<Item = LanguageRoot> {
56 self.fluent_files
57 .iter()
58 .map(|f| LanguageRoot::from(f.locale()))
59 .collect::<HashSet<_>>()
60 .into_iter()
61 }
62
63 pub fn locales_by_language_root(&self, root: &LanguageRoot) -> impl Iterator<Item = &Locale> {
65 self.fluent_files.iter().filter_map(|f| {
66 let locale = f.locale();
67 (LanguageRoot::from(locale) == *root).then_some(locale)
68 })
69 }
70
71 pub fn fluent_files_by_locale(&self, locale: &Locale) -> impl Iterator<Item = &FluentFile> {
74 let mut files = self
75 .fluent_files()
76 .iter()
77 .filter(|f| f.locale() == locale)
78 .collect::<Vec<_>>();
79 files.sort_by_key(|f| f.path());
80 files.into_iter()
81 }
82
83 pub fn canonical_locale(&self) -> &Locale {
85 &self.canonical
86 }
87
88 pub fn is_canonical_locale(&self, locale: &Locale) -> bool {
90 locale == self.canonical_locale()
91 }
92
93 pub fn primary_locales(&self) -> impl Iterator<Item = &Locale> {
95 self.primaries.iter()
96 }
97
98 pub fn is_primary_locale(&self, locale: &Locale) -> bool {
100 self.primary_locales().any(|p| p == locale)
101 }
102
103 pub fn base_locales(&self) -> impl Iterator<Item = &Locale> {
105 self.primaries
106 .iter()
107 .chain(std::iter::once(&self.canonical))
108 }
109
110 pub fn is_base_locale(&self, locale: &Locale) -> bool {
112 self.base_locales().any(|p| p == locale)
113 }
114
115 pub fn variant_locales(&self, base: &Locale) -> impl Iterator<Item = &Locale> {
117 let base_root = LanguageRoot::from(base);
118 self.fluent_files.iter().filter_map(move |f| {
119 let locale = f.locale();
120 let root = LanguageRoot::from(locale);
121 (base_root == root && base != locale).then_some(locale)
122 })
123 }
124
125 pub fn orphan_locales(&self) -> impl Iterator<Item = &Locale> {
127 let base_roots = Vec::from_iter(self.base_locales().map(LanguageRoot::from));
128 self.fluent_files.iter().filter_map(move |f| {
129 let locale = f.locale();
130 let root = LanguageRoot::from(locale);
131 (!base_roots.contains(&root)).then_some(locale)
132 })
133 }
134
135 pub fn is_orphan_locale(&self, locale: &Locale) -> bool {
137 self.orphan_locales().any(|p| p == locale)
138 }
139
140 pub fn rust_files(&self) -> &[RustFile] {
142 &self.rust_files
143 }
144}