Skip to content

Commit 2630120

Browse files
fix: generate proper file:// URIs and strip angle brackets in IRIs
Co-authored-by: aider (openai/gpt-5) <[email protected]>
1 parent 3ea1f01 commit 2630120

File tree

1 file changed

+55
-4
lines changed

1 file changed

+55
-4
lines changed

lib/src/ontology.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,50 @@ impl Default for OntologyLocation {
130130
}
131131
}
132132

133+
fn file_path_to_file_uri(p: &PathBuf) -> String {
134+
#[cfg(windows)]
135+
{
136+
let mut s = p.to_string_lossy().to_string();
137+
if s.contains('\\') {
138+
s = s.replace('\\', "/");
139+
}
140+
// Ensure leading slash for drive-letter paths (e.g., C:/...)
141+
if !s.starts_with('/') {
142+
if s.len() >= 2 && s.as_bytes()[1] == b':' {
143+
s = format!("/{s}");
144+
}
145+
}
146+
// Minimal percent-encoding for common problematic characters in paths
147+
let mut encoded = String::with_capacity(s.len());
148+
for ch in s.chars() {
149+
match ch {
150+
' ' => encoded.push_str("%20"),
151+
'#' => encoded.push_str("%23"),
152+
'?' => encoded.push_str("%3F"),
153+
'%' => encoded.push_str("%25"),
154+
_ => encoded.push(ch),
155+
}
156+
}
157+
return format!("file://{encoded}");
158+
}
159+
#[cfg(not(windows))]
160+
{
161+
let s = p.to_string_lossy();
162+
// Minimal percent-encoding for common problematic characters in paths
163+
let mut encoded = String::with_capacity(s.len());
164+
for ch in s.chars() {
165+
match ch {
166+
' ' => encoded.push_str("%20"),
167+
'#' => encoded.push_str("%23"),
168+
'?' => encoded.push_str("%3F"),
169+
'%' => encoded.push_str("%25"),
170+
_ => encoded.push(ch),
171+
}
172+
}
173+
return format!("file://{encoded}");
174+
}
175+
}
176+
133177
impl OntologyLocation {
134178
pub fn as_str(&self) -> &str {
135179
match self {
@@ -175,13 +219,20 @@ impl OntologyLocation {
175219
}
176220

177221
pub fn to_iri(&self) -> NamedNode {
178-
// if it is a file, convert it to a file:// IRI
179222
match self {
180223
OntologyLocation::File(p) => {
181-
let p = p.to_str().unwrap_or_default();
182-
NamedNode::new(format!("file://{p}")).unwrap()
224+
let iri = file_path_to_file_uri(p);
225+
NamedNode::new(iri).unwrap()
226+
}
227+
OntologyLocation::Url(u) => {
228+
// Strip angle brackets if present (e.g., "<http://...>")
229+
let iri = if u.starts_with('<') && u.ends_with('>') && u.len() >= 2 {
230+
u[1..u.len() - 1].to_string()
231+
} else {
232+
u.clone()
233+
};
234+
NamedNode::new(iri).unwrap()
183235
}
184-
OntologyLocation::Url(u) => NamedNode::new(u.clone()).unwrap(),
185236
}
186237
}
187238

0 commit comments

Comments
 (0)