use crate::maven::parse_maven_coordinate;
use toml_edit::{Item, Value};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LibraryDetails {
pub group: String,
pub artifact: String,
pub version: Option<String>,
pub version_ref: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PluginDetails {
pub id: String,
pub version: Option<String>,
pub version_ref: Option<String>,
}
pub struct TomlUtils;
impl TomlUtils {
pub fn extract_group_artifact(item: &Item) -> Option<(String, String)> {
if let Some(str_value) = item.as_str() {
return parse_maven_coordinate(str_value).map(|(g, a, _)| (g, a));
}
if let Some(inline_table) = item.as_inline_table() {
if let Some(module) = inline_table.get("module").and_then(|v| v.as_str()) {
return parse_maven_coordinate(module).map(|(g, a, _)| (g, a));
}
if let (Some(group), Some(name)) = (
inline_table.get("group").and_then(|v| v.as_str()),
inline_table.get("name").and_then(|v| v.as_str()),
) {
return Some((group.to_string(), name.to_string()));
}
}
if let Some(table) = item.as_table() {
if let Some(module) = table.get("module").and_then(|v| v.as_str()) {
return parse_maven_coordinate(module).map(|(g, a, _)| (g, a));
}
if let (Some(group), Some(name)) = (
table.get("group").and_then(|v| v.as_str()),
table.get("name").and_then(|v| v.as_str()),
) {
return Some((group.to_string(), name.to_string()));
}
}
None
}
pub fn extract_version(item: &Item) -> Option<String> {
if let Some(inline_table) = item.as_inline_table() {
return inline_table
.get("version")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
}
if let Some(table) = item.as_table() {
return table
.get("version")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
}
None
}
pub fn extract_version_ref(item: &Item) -> Option<String> {
if let Some(inline_table) = item.as_inline_table() {
return inline_table
.get("version")
.and_then(|item| item.as_inline_table())
.and_then(|table| table.get("ref"))
.and_then(|v| v.as_str())
.map(|s| s.to_string());
}
if let Some(table) = item.as_table() {
if let Some(version_item) = table.get("version") {
if let Some(as_table) = version_item.as_table() {
return as_table
.get("ref")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
}
if let Some(as_inline) = version_item.as_inline_table() {
return as_inline
.get("ref")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
}
}
}
None
}
pub fn update_version(item: &mut Item, new_version: &str) -> bool {
if item.as_str().is_some() {
*item = Item::Value(Value::from(new_version));
return true;
}
if let Some(inline_table) = item.as_inline_table_mut() {
inline_table.insert("version", Value::from(new_version));
return true;
}
if let Some(table) = item.as_table_mut() {
table.insert("version", Item::Value(Value::from(new_version)));
return true;
}
false
}
pub fn uses_version_ref(item: &Item, version_key: &str) -> bool {
Self::extract_version_ref(item)
.map(|key| key == version_key)
.unwrap_or(false)
}
pub fn extract_library_details(item: &Item) -> Option<LibraryDetails> {
if let Some(raw) = item.as_str() {
let (group, artifact, version) = parse_maven_coordinate(raw)?;
return Some(LibraryDetails {
group,
artifact,
version,
version_ref: None,
});
}
let (group, artifact) = Self::extract_group_artifact(item)?;
let version = Self::extract_version(item);
let version_ref = Self::extract_version_ref(item);
Some(LibraryDetails {
group,
artifact,
version,
version_ref,
})
}
pub fn extract_plugin_details(alias: &str, item: &Item) -> Option<PluginDetails> {
if let Some(version) = item.as_str() {
return Some(PluginDetails {
id: alias.to_string(),
version: Some(version.to_string()),
version_ref: None,
});
}
let id = if let Some(inline_table) = item.as_inline_table() {
inline_table
.get("id")
.and_then(|v| v.as_str())
.unwrap_or(alias)
.to_string()
} else if let Some(table) = item.as_table() {
table
.get("id")
.and_then(|v| v.as_str())
.unwrap_or(alias)
.to_string()
} else {
return None;
};
Some(PluginDetails {
id,
version: Self::extract_version(item),
version_ref: Self::extract_version_ref(item),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use toml_edit::DocumentMut;
#[test]
fn extracts_group_artifact_from_string() {
let doc: DocumentMut = r#"lib = "com.test:artifact:1.0.0""#.parse().unwrap();
let item = doc.get("lib").unwrap();
assert_eq!(
TomlUtils::extract_group_artifact(item),
Some(("com.test".to_string(), "artifact".to_string()))
);
}
#[test]
fn extracts_version_ref() {
let doc: DocumentMut =
r#"lib = { group = "com.test", name = "artifact", version = { ref = "core" } }"#
.parse()
.unwrap();
let item = doc.get("lib").unwrap();
assert_eq!(
TomlUtils::extract_version_ref(item),
Some("core".to_string())
);
}
#[test]
fn updates_inline_table_version() {
let mut doc: DocumentMut =
r#"lib = { group = "com.test", name = "artifact", version = "1.0.0" }"#
.parse()
.unwrap();
let item = doc.get_mut("lib").unwrap();
assert!(TomlUtils::update_version(item, "2.0.0"));
assert_eq!(
TomlUtils::extract_version(doc.get("lib").unwrap()).as_deref(),
Some("2.0.0")
);
}
#[test]
fn extracts_library_details_from_inline_definition() {
let doc: DocumentMut =
r#"lib = { group = "com.test", name = "artifact", version = "1.0.0" }"#
.parse()
.unwrap();
let item = doc.get("lib").unwrap();
let details = TomlUtils::extract_library_details(item).unwrap();
assert_eq!(details.group, "com.test");
assert_eq!(details.artifact, "artifact");
assert_eq!(details.version.as_deref(), Some("1.0.0"));
assert!(details.version_ref.is_none());
}
#[test]
fn extracts_library_details_with_version_reference() {
let doc: DocumentMut =
r#"lib = { module = "com.test:artifact", version = { ref = "core" } }"#
.parse()
.unwrap();
let item = doc.get("lib").unwrap();
let details = TomlUtils::extract_library_details(item).unwrap();
assert_eq!(details.group, "com.test");
assert_eq!(details.artifact, "artifact");
assert!(details.version.is_none());
assert_eq!(details.version_ref.as_deref(), Some("core"));
}
#[test]
fn extracts_plugin_details_from_inline_definition() {
let doc: DocumentMut = r#"plugin = { id = "org.jetbrains.kotlin.jvm", version = "1.9.0" }"#
.parse()
.unwrap();
let item = doc.get("plugin").unwrap();
let details = TomlUtils::extract_plugin_details("plugin", item).unwrap();
assert_eq!(details.id, "org.jetbrains.kotlin.jvm");
assert_eq!(details.version.as_deref(), Some("1.9.0"));
assert!(details.version_ref.is_none());
}
#[test]
fn extracts_plugin_details_with_version_reference() {
let doc: DocumentMut =
r#"plugin = { id = "org.jetbrains.kotlin.jvm", version = { ref = "kotlin" } }"#
.parse()
.unwrap();
let item = doc.get("plugin").unwrap();
let details = TomlUtils::extract_plugin_details("plugin", item).unwrap();
assert_eq!(details.id, "org.jetbrains.kotlin.jvm");
assert!(details.version.is_none());
assert_eq!(details.version_ref.as_deref(), Some("kotlin"));
}
}