1mod deser;
2pub mod error;
3pub mod generation;
4pub mod v1;
5
6use std::collections::HashMap;
7use std::fmt;
8use std::path::{Path, PathBuf};
9
10use serde::{Deserialize, Serialize};
11
12use crate::error::{BootspecError, SynthesizeError};
13use crate::generation::Generation;
14
15#[doc(hidden)]
16pub(crate) type Result<T, E = BootspecError> = core::result::Result<T, E>;
17
18#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
20pub struct SpecialisationName(pub String);
21
22impl fmt::Display for SpecialisationName {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 write!(f, "{}", self.0)
25 }
26}
27
28#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
30pub struct SystemConfigurationRoot(pub PathBuf);
31
32pub const JSON_FILENAME: &str = "boot.json";
34pub type Extensions = HashMap<String, serde_json::Value>;
36
37pub type BootSpec = v1::GenerationV1;
40pub type Specialisations = v1::SpecialisationsV1;
42pub type Specialisation = v1::SpecialisationV1;
44pub const SCHEMA_VERSION: u64 = v1::SCHEMA_VERSION;
46
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
49pub struct BootJson {
50 #[serde(flatten)]
51 pub generation: Generation,
52 #[serde(
53 default = "HashMap::new",
54 skip_serializing_if = "HashMap::is_empty",
55 deserialize_with = "deser::skip_generation_fields",
56 flatten
57 )]
58 pub extensions: Extensions,
59}
60
61impl BootJson {
62 pub fn synthesize_latest(generation_path: &Path) -> Result<BootJson> {
71 Self::synthesize_version(generation_path, SCHEMA_VERSION)
72 }
73
74 pub fn synthesize_version(generation_path: &Path, version: u64) -> Result<BootJson> {
83 let generation = match version {
84 v1::SCHEMA_VERSION => {
85 let generation = v1::GenerationV1::synthesize(generation_path)?;
86 Generation::V1(generation)
87 }
88 v => {
89 return Err(BootspecError::Synthesize(
90 SynthesizeError::UnsupportedVersion(v),
91 ))
92 }
93 };
94
95 Ok(BootJson {
96 generation,
97 extensions: HashMap::new(),
98 })
99 }
100}