diff --git a/cpp/src/api/convert.cpp b/cpp/src/api/convert.cpp index a4f34b07..1d40da1b 100644 --- a/cpp/src/api/convert.cpp +++ b/cpp/src/api/convert.cpp @@ -2,6 +2,41 @@ #include "api/exception/exception.h" +namespace { +std::optional convert(loot::rust::EdgeType edgeType) { + switch (edgeType) { + case loot::rust::EdgeType::Hardcoded: + return loot::EdgeType::hardcoded; + case loot::rust::EdgeType::MasterFlag: + return loot::EdgeType::masterFlag; + case loot::rust::EdgeType::Master: + return loot::EdgeType::master; + case loot::rust::EdgeType::MasterlistRequirement: + return loot::EdgeType::masterlistRequirement; + case loot::rust::EdgeType::UserRequirement: + return loot::EdgeType::userRequirement; + case loot::rust::EdgeType::MasterlistLoadAfter: + return loot::EdgeType::masterlistLoadAfter; + case loot::rust::EdgeType::UserLoadAfter: + return loot::EdgeType::userLoadAfter; + case loot::rust::EdgeType::MasterlistGroup: + return loot::EdgeType::masterlistGroup; + case loot::rust::EdgeType::UserGroup: + return loot::EdgeType::userGroup; + case loot::rust::EdgeType::RecordOverlap: + return loot::EdgeType::recordOverlap; + case loot::rust::EdgeType::AssetOverlap: + return loot::EdgeType::assetOverlap; + case loot::rust::EdgeType::TieBreak: + return loot::EdgeType::tieBreak; + case loot::rust::EdgeType::BlueprintMaster: + return loot::EdgeType::blueprintMaster; + default: + return std::nullopt; + } +} +} + namespace loot { // To public types ///////////////////// @@ -93,42 +128,9 @@ loot::PluginMetadata convert(const loot::rust::PluginMetadata& metadata) { return output; } -std::optional convert(uint8_t edgeType) { - switch (edgeType) { - case static_cast(loot::rust::EdgeType::Hardcoded): - return loot::EdgeType::hardcoded; - case static_cast(loot::rust::EdgeType::MasterFlag): - return loot::EdgeType::masterFlag; - case static_cast(loot::rust::EdgeType::Master): - return loot::EdgeType::master; - case static_cast(loot::rust::EdgeType::MasterlistRequirement): - return loot::EdgeType::masterlistRequirement; - case static_cast(loot::rust::EdgeType::UserRequirement): - return loot::EdgeType::userRequirement; - case static_cast(loot::rust::EdgeType::MasterlistLoadAfter): - return loot::EdgeType::masterlistLoadAfter; - case static_cast(loot::rust::EdgeType::UserLoadAfter): - return loot::EdgeType::userLoadAfter; - case static_cast(loot::rust::EdgeType::MasterlistGroup): - return loot::EdgeType::masterlistGroup; - case static_cast(loot::rust::EdgeType::UserGroup): - return loot::EdgeType::userGroup; - case static_cast(loot::rust::EdgeType::RecordOverlap): - return loot::EdgeType::recordOverlap; - case static_cast(loot::rust::EdgeType::AssetOverlap): - return loot::EdgeType::assetOverlap; - case static_cast(loot::rust::EdgeType::TieBreak): - return loot::EdgeType::tieBreak; - case static_cast(loot::rust::EdgeType::BlueprintMaster): - return loot::EdgeType::blueprintMaster; - default: - return std::nullopt; - } -} - loot::Vertex convert(const loot::rust::Vertex& vertex) { try { - const auto outEdgeType = convert(vertex.out_edge_type()); + const auto outEdgeType = ::convert(vertex.out_edge_type()); if (outEdgeType.has_value()) { return loot::Vertex(convert(vertex.name()), outEdgeType.value()); } else { diff --git a/cpp/src/database.rs b/cpp/src/database.rs index 945dbec9..8c9188c5 100644 --- a/cpp/src/database.rs +++ b/cpp/src/database.rs @@ -220,24 +220,25 @@ impl Database { #[repr(transparent)] pub struct Vertex(libloot::Vertex); -pub fn new_vertex(name: String) -> Box { - Box::new(Vertex(libloot::Vertex::new(name))) +pub fn new_vertex(name: String, out_edge_type: EdgeType) -> Result, VerboseError> { + let mut vertex = libloot::Vertex::new(name); + + if out_edge_type != EdgeType::None { + vertex = vertex.with_out_edge_type(out_edge_type.try_into()?); + } + + Ok(Box::new(Vertex(vertex))) } impl Vertex { // A value of 255 is used to indicate that there is no out edge. - pub fn out_edge_type(&self) -> Result { + pub fn out_edge_type(&self) -> Result { match self.0.out_edge_type() { - Some(e) => Ok(EdgeType::try_from(e)?.repr), - None => Ok(u8::MAX), + Some(e) => EdgeType::try_from(e).map_err(Into::into), + None => Ok(EdgeType::None), } } - pub fn set_out_edge_type(&mut self, out_edge_type: EdgeType) -> Result<(), VerboseError> { - self.0.set_out_edge_type(out_edge_type.try_into()?); - Ok(()) - } - pub fn boxed_clone(&self) -> Box { Box::new(Self(self.0.clone())) } diff --git a/cpp/src/lib.rs b/cpp/src/lib.rs index 6d33bcb4..b975408b 100644 --- a/cpp/src/lib.rs +++ b/cpp/src/lib.rs @@ -238,6 +238,7 @@ mod ffi { } pub enum EdgeType { + None, Hardcoded, MasterFlag, Master, @@ -512,13 +513,11 @@ mod ffi { extern "Rust" { type Vertex; - pub fn new_vertex(name: String) -> Box; + pub fn new_vertex(name: String, out_edge_type: EdgeType) -> Result>; pub fn name(&self) -> &str; - pub fn out_edge_type(&self) -> Result; - - pub fn set_out_edge_type(&mut self, #[into] out_edge_type: EdgeType) -> Result<()>; + pub fn out_edge_type(&self) -> Result; pub fn boxed_clone(&self) -> Box; } diff --git a/nodejs/src/database.rs b/nodejs/src/database.rs index 86854e8d..71c8975d 100644 --- a/nodejs/src/database.rs +++ b/nodejs/src/database.rs @@ -241,8 +241,14 @@ pub struct Vertex(libloot::Vertex); #[napi] impl Vertex { #[napi(constructor)] - pub fn new(name: String) -> Self { - Self(libloot::Vertex::new(name)) + pub fn new(name: String, out_edge_type: Option) -> Self { + let mut vertex = libloot::Vertex::new(name); + + if let Some(out_edge_type) = out_edge_type { + vertex = vertex.with_out_edge_type(out_edge_type.into()); + } + + Self(vertex) } #[napi(getter)] @@ -257,12 +263,6 @@ impl Vertex { .map(|e| e.try_into().map_err(Into::into)) .transpose() } - - #[napi(setter)] - pub fn set_out_edge_type(&mut self, out_edge_type: EdgeType) { - let out_edge_type = out_edge_type.into(); - self.0.set_out_edge_type(out_edge_type); - } } impl From for Vertex { diff --git a/python/src/database.rs b/python/src/database.rs index 2bd7d8a9..35331f1e 100644 --- a/python/src/database.rs +++ b/python/src/database.rs @@ -1,5 +1,4 @@ use std::{ - hash::{DefaultHasher, Hash, Hasher}, path::PathBuf, sync::{Arc, RwLock}, }; @@ -225,7 +224,7 @@ impl From>> for Database { } } -#[pyclass(eq, ord, str = "{0:?}")] +#[pyclass(eq, ord, frozen, hash, str = "{0:?}")] #[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] pub struct Vertex(libloot::Vertex); @@ -250,13 +249,6 @@ impl Vertex { .transpose() } - #[setter] - fn set_out_edge_type(&mut self, out_edge_type: EdgeType) -> Result<(), VerboseError> { - let out_edge_type = out_edge_type.try_into()?; - self.0.set_out_edge_type(out_edge_type); - Ok(()) - } - fn __repr__(slf: &Bound<'_, Self>) -> PyResult { let class_name = slf.get_type().qualname()?; let inner = &slf.borrow().0; @@ -267,12 +259,6 @@ impl Vertex { inner.out_edge_type().map_or(NONE_REPR, repr_edge_type), )) } - - fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.0.hash(&mut hasher); - hasher.finish() - } } impl From for Vertex { diff --git a/src/sorting/vertex.rs b/src/sorting/vertex.rs index 0b96ae33..0c4b8f38 100644 --- a/src/sorting/vertex.rs +++ b/src/sorting/vertex.rs @@ -59,7 +59,7 @@ impl Vertex { /// Set the type of the edge going from this vertex to the next in the path. #[must_use] pub fn with_out_edge_type(mut self, out_edge_type: EdgeType) -> Self { - self.set_out_edge_type(out_edge_type); + self.out_edge_type = Some(out_edge_type); self } @@ -72,10 +72,4 @@ impl Vertex { pub fn out_edge_type(&self) -> Option { self.out_edge_type } - - /// Set the type of the edge going from this vertex to the next in the path. - pub fn set_out_edge_type(&mut self, out_edge_type: EdgeType) -> &mut Self { - self.out_edge_type = Some(out_edge_type); - self - } }