rdf_structural_model/
blank_node.rs1use borrow_or_share::Bos;
4use iri_rfc3987::Iri;
5use serde::{
6 Deserialize,
7 Deserializer,
8};
9
10use crate::ModelError;
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
18#[serde(
19 deny_unknown_fields,
20 bound(
21 serialize = "Text: serde::Serialize",
22 deserialize = "Text: serde::Deserialize<'de>, Iri<Text>: serde::Deserialize<'de>"
23 )
24)]
25pub struct BlankNodeId<Text: Bos<str> + AsRef<str> = String> {
26 scope: Iri<Text>,
27 #[serde(deserialize_with = "BlankNodeId::deserialize_label")]
28 label: Text,
29}
30
31impl<Text: Bos<str> + AsRef<str>> BlankNodeId<Text> {
32 pub fn try_new(scope: Iri<Text>, label: Text) -> Result<Self, ModelError> {
38 Self::validate_label(label.as_ref())?;
39 Ok(Self { scope, label })
40 }
41
42 #[must_use]
44 pub const fn scope(&self) -> &Iri<Text> {
45 &self.scope
46 }
47
48 #[must_use]
50 pub fn label(&self) -> &str {
51 self.label.as_ref()
52 }
53
54 fn validate_label(label: &str) -> Result<(), ModelError> {
55 if label.is_empty() {
56 return Err(ModelError::EmptyBlankNode);
57 }
58 Ok(())
59 }
60
61 fn deserialize_label<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Text, D::Error>
62 where
63 Text: Deserialize<'de>,
64 {
65 let label = Text::deserialize(deserializer)?;
66 Self::validate_label(label.as_ref()).map_err(serde::de::Error::custom)?;
67 Ok(label)
68 }
69}
70
71impl BlankNodeId<String> {
72 #[must_use]
74 pub fn as_ref(&self) -> BlankNodeId<&str> {
75 BlankNodeId {
76 scope: self.scope.borrow(),
77 label: &self.label,
78 }
79 }
80}