jsoncall 0.0.3

A simple asynchronous JSON-RPC 2.0 library leveraging Rust's type system
Documentation
use std::any::Any;
use std::fmt;

use serde_json::Value;

pub(crate) fn downcast<T: 'static, S: 'static>(value: S) -> Result<T, S> {
    let mut value = Some(value);
    if let Some(value) = <dyn Any>::downcast_mut::<Option<T>>(&mut value) {
        Ok(value.take().unwrap())
    } else {
        Err(value.unwrap())
    }
}
pub(crate) fn write_string_no_escape(value: &Value, f: &mut fmt::Formatter) -> fmt::Result {
    if f.alternate() {
        write_string_pretty_no_escape(value, f, 0)
    } else {
        write_string_no_escape_oneline(value, f)
    }
}

fn write_string_no_escape_oneline(value: &Value, f: &mut fmt::Formatter) -> fmt::Result {
    match value {
        Value::Null => write!(f, "null"),
        Value::Bool(b) => write!(f, "{b}"),
        Value::Number(n) => write!(f, "{n}"),
        Value::String(s) => write!(f, "{s}"),
        Value::Array(arr) => {
            write!(f, "[")?;
            let mut first = true;
            for item in arr {
                if !first {
                    write!(f, ",")?;
                }
                first = false;
                write_string_no_escape(item, f)?;
            }
            write!(f, "]")
        }
        Value::Object(obj) => {
            write!(f, "{{")?;
            let mut first = true;
            for (key, value) in obj {
                if !first {
                    write!(f, ",")?;
                }
                first = false;
                write!(f, "{key}:")?;
                write_string_no_escape(value, f)?;
            }
            write!(f, "}}")
        }
    }
}

fn write_string_pretty_no_escape(
    value: &Value,
    f: &mut fmt::Formatter,
    indent: usize,
) -> fmt::Result {
    match value {
        Value::Null => write!(f, "null"),
        Value::Bool(b) => write!(f, "{b}"),
        Value::Number(n) => write!(f, "{n}"),
        Value::String(s) => write!(f, "{s}"),
        Value::Array(arr) => {
            if arr.is_empty() {
                return write!(f, "[]");
            }

            writeln!(f, "[")?;
            let next_indent = indent + 2;

            for (i, item) in arr.iter().enumerate() {
                write!(f, "{:indent$}", "", indent = next_indent)?;
                write_string_pretty_no_escape(item, f, next_indent)?;

                if i < arr.len() - 1 {
                    writeln!(f, ",")?;
                } else {
                    writeln!(f)?;
                }
            }

            write!(f, "{:indent$}]", "", indent = indent)
        }
        Value::Object(obj) => {
            if obj.is_empty() {
                return write!(f, "{{}}");
            }

            writeln!(f, "{{")?;
            let next_indent = indent + 2;

            let entries: Vec<_> = obj.iter().collect();
            for (i, (key, value)) in entries.iter().enumerate() {
                write!(f, "{:indent$}\"{key}\": ", "", indent = next_indent)?;
                write_string_pretty_no_escape(value, f, next_indent)?;

                if i < entries.len() - 1 {
                    writeln!(f, ",")?;
                } else {
                    writeln!(f)?;
                }
            }

            write!(f, "{:indent$}}}", "", indent = indent)
        }
    }
}