use crate::lossy::relations::Relations;
use deb822_fast::FromDeb822Paragraph;
use deb822_fast::{FromDeb822, ToDeb822};
use std::collections::HashMap;
use std::path::PathBuf;
fn deserialize_env(s: &str) -> Result<HashMap<String, String>, String> {
let mut env = HashMap::new();
for line in s.lines() {
if line.trim().is_empty() {
continue;
}
let (key, value) = match line.split_once("=") {
Some((key, value)) => {
if value.starts_with('"') && value.ends_with('"') {
let value = value[1..value.len() - 1].to_string();
(key, value)
} else {
(key, value.to_string())
}
}
None => {
return Err("Invalid environment variable".to_string());
}
};
env.insert(key.to_string(), value.to_string());
}
Ok(env)
}
fn serialize_env(env: &HashMap<String, String>) -> String {
let mut s = String::new();
for (key, value) in env {
s.push_str(&format!("{}={}\n", key, value));
}
s
}
fn deserialize_version(s: &str) -> Result<debversion::Version, String> {
s.parse().map_err(|e: debversion::ParseError| e.to_string())
}
fn serialize_version(version: &debversion::Version) -> String {
version.to_string()
}
fn serialize_pathbuf(path: &std::path::Path) -> String {
path.display().to_string()
}
fn deserialize_pathbuf(s: &str) -> Result<PathBuf, String> {
Ok(PathBuf::from(s))
}
#[derive(FromDeb822, ToDeb822)]
pub struct Buildinfo {
#[deb822(field = "Format")]
format: String,
#[deb822(field = "Build-Architecture")]
build_architecture: String,
#[deb822(field = "Source")]
source: String,
#[deb822(field = "Binary")]
binary: Option<String>,
#[deb822(field = "Architecture")]
architecture: String,
#[deb822(
field = "Version",
deserialize_with = deserialize_version,
serialize_with = serialize_version
)]
version: debversion::Version,
#[deb822(field = "Binary-Only-Changes")]
binary_only_changes: Option<String>,
#[deb822(field = "Checksums-Sha256")]
checksums_sha256: Option<String>,
#[deb822(field = "Checksums-Sha1")]
checksums_sha1: Option<String>,
#[deb822(field = "Checksums-Md5")]
checksums_md5: Option<String>,
#[deb822(field = "Build-Origin")]
build_origin: Option<String>,
#[deb822(field = "Build-Date")]
build_date: Option<String>,
#[deb822(field = "Build-Tainted-By")]
build_tainted_by: Option<String>,
#[deb822(field = "Build-Path", deserialize_with = deserialize_pathbuf, serialize_with = serialize_pathbuf)]
build_path: Option<PathBuf>,
#[deb822(
field = "Environment",
deserialize_with = deserialize_env,
serialize_with = serialize_env
)]
environment: Option<HashMap<String, String>>,
#[deb822(field = "Installed-Build-Depends")]
installed_build_depends: Option<Relations>,
}
impl std::str::FromStr for Buildinfo {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let para: deb822_fast::Paragraph =
s.parse().map_err(|e: deb822_fast::Error| e.to_string())?;
Self::from_paragraph(¶)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_buildinfo() {
let input = include_str!("../../testdata/ruff.buildinfo");
let buildinfo = Buildinfo::from_str(input).unwrap();
assert_eq!(buildinfo.format, "1.0");
}
}