clippy: change ToString impl to Display

- write directly to formatter, eliminating intermediate String allocations
- take Value by reference eliminating clones
- remove trim() called on the result of  QueryResolution::to_string
    - we only  emit "true", "false", or "[<resolutions>]"
      neither of which contains trailing or leading withespace,
      so the calls was effectively a noop
This commit is contained in:
Bennet Bleßmann
2024-07-06 13:28:44 +02:00
parent 722975d77e
commit 6386e70584

View File

@@ -3,6 +3,8 @@ use dashu::*;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Display;
use std::fmt::Write;
pub type QueryResult = Result<QueryResolution, String>; pub type QueryResult = Result<QueryResolution, String>;
@@ -13,17 +15,21 @@ pub enum QueryResolution {
Matches(Vec<QueryMatch>), Matches(Vec<QueryMatch>),
} }
pub fn prolog_value_to_json_string(value: Value) -> String { pub fn write_prolog_value_as_json<W: Write>(
writer: &mut W,
value: &Value,
) -> Result<(), std::fmt::Error> {
match value { match value {
Value::Integer(i) => format!("{}", i), Value::Integer(i) => write!(writer, "{}", i),
Value::Float(f) => format!("{}", f), Value::Float(f) => write!(writer, "{}", f),
Value::Rational(r) => format!("{}", r), Value::Rational(r) => write!(writer, "{}", r),
Value::Atom(a) => format!("{}", a.as_str()), Value::Atom(a) => writer.write_str(&a.as_str()),
Value::String(s) => { Value::String(s) => {
if let Err(_e) = serde_json::from_str::<serde_json::Value>(s.as_str()) { if let Err(_e) = serde_json::from_str::<serde_json::Value>(s.as_str()) {
//treat as string literal //treat as string literal
//escape double quotes //escape double quotes
format!( write!(
writer,
"\"{}\"", "\"{}\"",
s.replace('\"', "\\\"") s.replace('\"', "\\\"")
.replace('\n', "\\n") .replace('\n', "\\n")
@@ -32,60 +38,71 @@ pub fn prolog_value_to_json_string(value: Value) -> String {
) )
} else { } else {
//return valid json string //return valid json string
s writer.write_str(&s)
} }
} }
Value::List(l) => { Value::List(l) => {
let mut string_result = "[".to_string(); writer.write_char('[')?;
for (i, v) in l.iter().enumerate() { if let Some((first, rest)) = l.split_first() {
if i > 0 { write_prolog_value_as_json(writer, first)?;
string_result.push(',');
for other in rest {
writer.write_char(',')?;
write_prolog_value_as_json(writer, other)?;
} }
string_result.push_str(&prolog_value_to_json_string(v.clone()));
} }
string_result.push(']'); writer.write_char(']')
string_result
} }
Value::Structure(s, l) => { Value::Structure(s, l) => {
let mut string_result = format!("\"{}\":[", s.as_str()); write!(writer, "\"{}\":[", s.as_str())?;
for (i, v) in l.iter().enumerate() {
if i > 0 { if let Some((first, rest)) = l.split_first() {
string_result.push(','); write_prolog_value_as_json(writer, first)?;
for other in rest {
writer.write_char(',')?;
write_prolog_value_as_json(writer, other)?;
} }
string_result.push_str(&prolog_value_to_json_string(v.clone()));
} }
string_result.push(']'); writer.write_char(']')
string_result
} }
_ => "null".to_string(), _ => writer.write_str("null"),
} }
} }
fn prolog_match_to_json_string(query_match: &QueryMatch) -> String { fn write_prolog_match_as_json<W: std::fmt::Write>(
let mut string_result = "{".to_string(); writer: &mut W,
for (i, (k, v)) in query_match.bindings.iter().enumerate() { query_match: &QueryMatch,
if i > 0 { ) -> Result<(), std::fmt::Error> {
string_result.push(','); writer.write_char('{')?;
let mut iter = query_match.bindings.iter();
if let Some((k, v)) = iter.next() {
write!(writer, "\"{k}\":")?;
write_prolog_value_as_json(writer, v)?;
for (k, v) in iter {
write!(writer, ",\"{k}\":")?;
write_prolog_value_as_json(writer, v)?;
} }
string_result.push_str(&format!(
"\"{}\":{}",
k,
prolog_value_to_json_string(v.clone())
));
} }
string_result.push('}'); writer.write_char('}')
string_result
} }
impl ToString for QueryResolution { impl Display for QueryResolution {
fn to_string(&self) -> String { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
QueryResolution::True => "true".to_string(), QueryResolution::True => f.write_str("true"),
QueryResolution::False => "false".to_string(), QueryResolution::False => f.write_str("false"),
QueryResolution::Matches(matches) => { QueryResolution::Matches(matches) => {
let matches_json: Vec<String> = f.write_char('[')?;
matches.iter().map(prolog_match_to_json_string).collect(); if let Some((first, rest)) = matches.split_first() {
format!("[{}]", matches_json.join(",")) write_prolog_match_as_json(f, first)?;
for other in rest {
f.write_char(',')?;
write_prolog_match_as_json(f, other)?;
}
}
f.write_char(']')
} }
} }
} }