use color_eyre::eyre::eyre;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub type Result<T> = color_eyre::eyre::Result<T>;
pub const RIMLOC_SCHEMA_VERSION: u32 = 1;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransUnit {
pub key: String,
pub source: Option<String>,
pub path: PathBuf,
pub line: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PoEntry {
pub key: String,
pub value: String,
pub reference: Option<String>,
}
#[derive(Debug, Error)]
pub enum RimLocError {
#[error("{0}")]
Other(String),
}
pub fn parse_simple_po(input: &str) -> Result<Vec<PoEntry>> {
let mut entries = Vec::new();
let mut cur_ref: Option<String> = None;
let mut cur_id: Option<String> = None;
fn unquote(raw: &str) -> String {
let trimmed = raw.trim();
if trimmed.starts_with('"') && trimmed.ends_with('"') && trimmed.len() >= 2 {
trimmed[1..trimmed.len() - 1].to_string()
} else {
trimmed.to_string()
}
}
for line in input.lines() {
let trimmed = line.trim();
if trimmed.is_empty() {
continue;
}
if let Some(rest) = trimmed.strip_prefix("#:") {
cur_ref = Some(rest.trim().to_string());
continue;
}
if let Some(rest) = trimmed.strip_prefix("msgid") {
let eq = rest
.trim_start()
.strip_prefix(' ')
.unwrap_or(rest)
.trim_start_matches('=');
cur_id = Some(unquote(eq.trim()));
continue;
}
if let Some(rest) = trimmed.strip_prefix("msgstr") {
let eq = rest
.trim_start()
.strip_prefix(' ')
.unwrap_or(rest)
.trim_start_matches('=');
let val = unquote(eq.trim());
if let Some(id) = cur_id.take() {
entries.push(PoEntry {
key: id,
value: val,
reference: cur_ref.take(),
});
} else {
return Err(eyre!("Malformed PO entry: msgstr without msgid"));
}
}
}
Ok(entries)
}