vortex_edition/
session.rs1use std::any::Any;
8use std::collections::BTreeMap;
9use std::sync::Arc;
10
11use parking_lot::RwLock;
12use vortex_session::SessionExt;
13use vortex_session::SessionGuard;
14use vortex_session::SessionVar;
15use vortex_session::registry::Id;
16
17use crate::Edition;
18use crate::EditionDeclaration;
19use crate::EditionError;
20use crate::EditionId;
21use crate::EditionInclusion;
22use crate::parse_release;
23
24#[derive(Clone, Debug, Default)]
32pub struct EditionSession {
33 inner: Arc<RwLock<Inner>>,
34}
35
36#[derive(Debug, Default)]
37struct Inner {
38 editions: BTreeMap<String, Edition>,
40 inclusions: BTreeMap<Id, EditionInclusion>,
42}
43
44impl EditionSession {
45 pub fn empty() -> Self {
47 Self {
48 inner: Arc::new(RwLock::new(Inner::default())),
49 }
50 }
51
52 pub fn declare(&self, declaration: &EditionDeclaration) -> Result<(), EditionError> {
56 self.declare_edition(declaration.edition)?;
57 for encoding in declaration.added {
58 self.declare_inclusion(EditionInclusion::new(*encoding, declaration.edition.id))?;
59 }
60 Ok(())
61 }
62
63 pub fn declare_edition(&self, edition: Edition) -> Result<(), EditionError> {
65 let mut inner = self.inner.write();
66 let key = edition.id.to_string();
67 if inner.editions.contains_key(&key) {
68 return Err(EditionError::new(format!("duplicate edition {key}")));
69 }
70 inner.editions.insert(key, edition);
71 Ok(())
72 }
73
74 pub fn declare_inclusion(&self, inclusion: EditionInclusion) -> Result<(), EditionError> {
77 let mut inner = self.inner.write();
78 if inner.inclusions.contains_key(&inclusion.encoding_id) {
79 return Err(EditionError::new(format!(
80 "duplicate edition inclusion for encoding {}",
81 inclusion.encoding_id
82 )));
83 }
84 inner.inclusions.insert(inclusion.encoding_id, inclusion);
85 Ok(())
86 }
87
88 pub fn editions(&self) -> Vec<Edition> {
92 let mut editions: Vec<Edition> = self.inner.read().editions.values().copied().collect();
93 editions.sort_by_key(|e| (e.id.family, e.id.year, e.id.month, e.id.version));
94 editions
95 }
96
97 pub fn find(&self, id: &EditionId) -> Option<Edition> {
99 self.inner.read().editions.get(&id.to_string()).copied()
100 }
101
102 pub fn current(&self, family: &str) -> Option<Edition> {
104 self.editions()
105 .into_iter()
106 .filter(|e| e.id.family == family && !e.is_draft())
107 .next_back()
108 }
109
110 pub fn encodings_in(&self, edition: &EditionId) -> Vec<EditionInclusion> {
113 self.inner
115 .read()
116 .inclusions
117 .values()
118 .filter(|inclusion| inclusion.since.is_at_or_before(edition))
119 .copied()
120 .collect()
121 }
122
123 pub fn validate(&self) -> Result<(), EditionError> {
128 let editions = self.editions();
129
130 for edition in &editions {
131 edition.id.validate()?;
132 if let Some(version) = edition.min_vortex_version
133 && parse_release(version).is_none()
134 {
135 return Err(EditionError::new(format!(
136 "edition {} declares malformed min_vortex_version {version:?}",
137 edition.id
138 )));
139 }
140 }
141
142 for pair in editions.windows(2) {
145 let (prev, next) = (&pair[0], &pair[1]);
146 if prev.id.family == next.id.family && prev.is_draft() && !next.is_draft() {
147 return Err(EditionError::new(format!(
148 "frozen edition {} follows draft {}; drafts must be newest in a family",
149 next.id, prev.id,
150 )));
151 }
152 }
153
154 let inner = self.inner.read();
155 for inclusion in inner.inclusions.values() {
156 inclusion.validate()?;
157
158 let Some(edition) = inner.editions.get(&inclusion.since.to_string()) else {
159 return Err(EditionError::new(format!(
160 "encoding {} is included in undeclared edition {}",
161 inclusion.encoding_id, inclusion.since
162 )));
163 };
164
165 if let Some(required) = inclusion.required_vortex_release.and_then(parse_release)
166 && let Some(declared) = edition.min_vortex_version.and_then(parse_release)
167 && required > declared
168 {
169 return Err(EditionError::new(format!(
170 "encoding {} requires release {}, newer than edition {}'s declared \
171 min_vortex_version",
172 inclusion.encoding_id,
173 inclusion.required_vortex_release.unwrap_or_default(),
174 edition.id,
175 )));
176 }
177 }
178
179 Ok(())
180 }
181}
182
183impl SessionVar for EditionSession {
184 fn as_any(&self) -> &dyn Any {
185 self
186 }
187
188 fn as_any_mut(&mut self) -> &mut dyn Any {
189 self
190 }
191}
192
193pub trait EditionSessionExt: SessionExt {
195 fn editions(&self) -> SessionGuard<'_, EditionSession> {
197 self.get::<EditionSession>()
198 }
199}
200
201impl<S: SessionExt> EditionSessionExt for S {}