Adds proper escaping of string literals

pull/10/head
Tpt 6 years ago
parent df66546d3e
commit 08d7497706
  1. 1
      src/lib.rs
  2. 7
      src/model/data.rs
  3. 73
      src/utils.rs

@ -6,3 +6,4 @@ extern crate uuid;
pub mod model;
pub mod rio;
pub mod store;
mod utils;

@ -7,6 +7,7 @@ use std::str::FromStr;
use std::sync::Arc;
use url::ParseError;
use url::Url;
use utils::Escaper;
use uuid::Uuid;
/// A RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
@ -163,10 +164,10 @@ impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_plain() {
self.language()
.map(|lang| write!(f, "\"{}\"@{}", self.value(), lang))
.unwrap_or_else(|| write!(f, "\"{}\"", self.value()))
.map(|lang| write!(f, "\"{}\"@{}", self.value().escape(), lang))
.unwrap_or_else(|| write!(f, "\"{}\"", self.value().escape()))
} else {
write!(f, "\"{}\"^^{}", self.value(), self.datatype())
write!(f, "\"{}\"^^{}", self.value().escape(), self.datatype())
}
}
}

@ -0,0 +1,73 @@
pub trait Escaper {
fn escape(&self) -> String;
}
impl<'a> Escaper for &'a str {
fn escape(&self) -> String {
self.chars().flat_map(|c| EscapeRDF::new(c)).collect()
}
}
/// Customized version of EscapeDefault of the Rust standard library
struct EscapeRDF {
state: EscapeRdfState,
}
enum EscapeRdfState {
Done,
Char(char),
Backslash(char),
}
impl EscapeRDF {
fn new(c: char) -> EscapeRDF {
EscapeRDF {
state: match c {
'\t' => EscapeRdfState::Backslash('t'),
'\u{08}' => EscapeRdfState::Backslash('b'),
'\n' => EscapeRdfState::Backslash('n'),
'\r' => EscapeRdfState::Backslash('r'),
'\u{0C}' => EscapeRdfState::Backslash('f'),
'\\' | '\'' | '"' => EscapeRdfState::Backslash(c),
c => EscapeRdfState::Char(c),
},
}
}
}
impl Iterator for EscapeRDF {
type Item = char;
fn next(&mut self) -> Option<char> {
match self.state {
EscapeRdfState::Backslash(c) => {
self.state = EscapeRdfState::Char(c);
Some('\\')
}
EscapeRdfState::Char(c) => {
self.state = EscapeRdfState::Done;
Some(c)
}
EscapeRdfState::Done => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.len();
(n, Some(n))
}
fn count(self) -> usize {
self.len()
}
}
impl ExactSizeIterator for EscapeRDF {
fn len(&self) -> usize {
match self.state {
EscapeRdfState::Done => 0,
EscapeRdfState::Char(_) => 1,
EscapeRdfState::Backslash(_) => 2,
}
}
}
Loading…
Cancel
Save