Files
sprout/src/generators/bls/entry.rs

123 lines
3.6 KiB
Rust
Raw Normal View History

2025-10-13 01:54:03 -07:00
use anyhow::{Error, Result};
use std::str::FromStr;
/// Represents a parsed BLS entry.
/// Fields unrelated to Sprout are not included.
2025-10-13 01:54:03 -07:00
#[derive(Default, Debug, Clone)]
pub struct BlsEntry {
/// The title of the entry.
2025-10-13 01:54:03 -07:00
pub title: Option<String>,
/// The options to pass to the entry.
2025-10-13 01:54:03 -07:00
pub options: Option<String>,
/// The path to the linux kernel.
2025-10-13 01:54:03 -07:00
pub linux: Option<String>,
/// The path to the initrd.
2025-10-13 01:54:03 -07:00
pub initrd: Option<String>,
/// The path to an EFI image.
2025-10-13 01:54:03 -07:00
pub efi: Option<String>,
}
/// Parser for a BLS entry.
2025-10-13 01:54:03 -07:00
impl FromStr for BlsEntry {
type Err = Error;
/// Parses the `input` as a BLS entry file.
2025-10-13 01:54:03 -07:00
fn from_str(input: &str) -> Result<Self> {
// All the fields in a BLS entry we understand.
// Set all to None initially.
2025-10-13 01:54:03 -07:00
let mut title: Option<String> = None;
let mut options: Option<String> = None;
let mut linux: Option<String> = None;
let mut initrd: Option<String> = None;
let mut efi: Option<String> = None;
// Iterate over each line in the input and parse it.
2025-10-13 01:54:03 -07:00
for line in input.lines() {
// Trim the line.
2025-10-13 01:54:03 -07:00
let line = line.trim();
// Split the line once by whitespace.
let Some((key, value)) = line.split_once(char::is_whitespace) else {
2025-10-13 01:54:03 -07:00
continue;
};
// Match the key to a field we understand.
2025-10-13 01:54:03 -07:00
match key {
// The title of the entry.
2025-10-13 01:54:03 -07:00
"title" => {
title = Some(value.trim().to_string());
}
// The options to pass to the entry.
2025-10-13 01:54:03 -07:00
"options" => {
options = Some(value.trim().to_string());
}
// The path to the linux kernel.
2025-10-13 01:54:03 -07:00
"linux" => {
linux = Some(value.trim().to_string());
}
// The path to the initrd.
2025-10-13 01:54:03 -07:00
"initrd" => {
initrd = Some(value.trim().to_string());
}
// The path to an EFI image.
2025-10-13 01:54:03 -07:00
"efi" => {
efi = Some(value.trim().to_string());
}
// Ignore any other key.
2025-10-13 01:54:03 -07:00
_ => {
continue;
}
}
}
// Produce a BLS entry from the parsed fields.
Ok(Self {
2025-10-13 01:54:03 -07:00
title,
options,
linux,
initrd,
efi,
})
}
}
impl BlsEntry {
/// Checks if this BLS entry is something we can actually boot in Sprout.
2025-10-13 01:54:03 -07:00
pub fn is_valid(&self) -> bool {
self.linux.is_some() || self.efi.is_some()
}
/// Fetches the path to an EFI bootable image to boot, if any.
/// This prioritizes the linux field over efi.
/// It also converts / to \\ to match EFI path style.
2025-10-13 01:54:03 -07:00
pub fn chainload_path(&self) -> Option<String> {
self.linux
.clone()
.or(self.efi.clone())
.map(|path| path.replace('/', "\\").trim_start_matches('\\').to_string())
2025-10-13 01:54:03 -07:00
}
/// Fetches the path to an initrd to pass to the kernel, if any.
/// It also converts / to \\ to match EFI path style.
2025-10-13 01:54:03 -07:00
pub fn initrd_path(&self) -> Option<String> {
self.initrd
.clone()
.map(|path| path.replace('/', "\\").trim_start_matches('\\').to_string())
2025-10-13 01:54:03 -07:00
}
/// Fetches the options to pass to the kernel, if any.
2025-10-13 01:54:03 -07:00
pub fn options(&self) -> Option<String> {
self.options.clone()
}
/// Fetches the title of the entry, if any.
2025-10-13 01:54:03 -07:00
pub fn title(&self) -> Option<String> {
self.title.clone()
}
}