jsonpiler 0.10.1

a Json syntax programming language for Windows
Documentation
use crate::prelude::*;
impl Pos<Parser> {
  pub(crate) fn comment(
    &mut self,
    out: &mut String,
    offset: u32,
    indentation: u32,
    default_indent: bool,
  ) {
    if self.val.comments.range(..=offset).next().is_none() {
      if default_indent {
        indent(out, indentation);
      }
      return;
    }
    let mut comments = self.val.comments.range(..=offset).clone().peekable();
    if let Some((_, comment)) = comments.peek() {
      if comment.leading {
        indent(out, indentation);
      } else {
        out.push(' ');
      }
    }
    for (_, comment) in comments {
      out.push_str(&comment.text);
      indent(out, indentation);
    }
    self.val.comments.retain(|&key, _| key > offset);
  }
  pub(crate) fn comment_sep(&mut self, out: &mut String, size: u32, offset: u32, indentation: u32) {
    if size < LINE_MAX {
      out.push(' ');
    }
    self.comment(out, offset, indentation, size >= LINE_MAX);
  }
  pub(crate) fn format(&mut self) -> Option<String> {
    let parsed = self.parse_jspl().ok()?;
    let mut out = String::new();
    let size = self.sizeof_json(&parsed)?;
    for (_, comment) in self.val.comments.range(..=parsed.pos.offset) {
      out.push_str(&comment.text);
      out.push('\n');
    }
    self.val.comments.retain(|&key, _| key > parsed.pos.offset);
    if let Object(Lit(object)) = parsed.val {
      self.format_block(&mut out, &object, size, 0)?;
    } else {
      self.format_json(&mut out, &parsed, 0)?;
    }
    self.comment(&mut out, self.pos.offset, 0, true);
    Some(out)
  }
  pub(crate) fn format_array(
    &mut self,
    out: &mut String,
    size: u32,
    array: &[Pos<Json>],
    indentation: u32,
  ) -> Option<()> {
    if array.is_empty() {
      out.push_str("[]");
      return Some(());
    }
    out.push('[');
    for (idx, item) in array.iter().enumerate() {
      if idx != 0 {
        out.push(',');
      }
      self.format_json_sep(out, size, item.pos.offset + 1, item, indentation)?;
    }
    self.comment_sep(out, size, self.pos.offset, indentation);
    out.push(']');
    Some(())
  }
  pub(crate) fn format_json(
    &mut self,
    out: &mut String,
    json: &Pos<Json>,
    indentation: u32,
  ) -> Option<()> {
    match &json.val {
      Null(Lit(())) | Int(Lit(_)) | Bool(Lit(_)) | Str(Lit(_)) | Float(Lit(_)) => {
        out.push_str(self.get_slice(json.pos).ok()?);
      }
      Array(Lit(array)) => {
        let size = self.sizeof_json(json)? + indentation * 2;
        self.format_array(out, size, array, indentation)?;
      }
      Object(Lit(object)) => {
        let size = self.sizeof_json(json)? + indentation * 2;
        self.format_object(out, size, json.pos, object, indentation)?;
      }
      Null(Var(_)) | Int(Var(_)) | Str(Var(_)) | Object(Var(_)) | Array(Var(_)) | Bool(Var(_))
      | Float(Var(_)) => return None,
    }
    Some(())
  }
  pub(crate) fn format_json_sep(
    &mut self,
    out: &mut String,
    size: u32,
    offset: u32,
    json: &Pos<Json>,
    indentation: u32,
  ) -> Option<()> {
    let val_size = (indentation + 1) * 2 + self.sizeof_json(json)?;
    self.comment_sep(
      out,
      size,
      offset,
      indentation + u32::from(val_size < LINE_MAX || !json.val.is_block()),
    );
    self.format_json(out, json, indentation + 1)
  }
  pub(crate) fn sizeof_json(&self, json: &Pos<Json>) -> Option<u32> {
    match &json.val {
      Null(Lit(())) | Int(Lit(_)) | Bool(Lit(_)) | Float(Lit(_)) | Str(Lit(_)) => {
        Some(json.pos.size)
      }
      Array(Lit(array)) => {
        let mut acc = 2;
        for item in array {
          acc += self.sizeof_json(item)? + 2;
        }
        Some(acc)
      }
      Object(Lit(object)) => {
        if object.len() == 1 {
          self.sizeof_key_val(&object[0])
        } else {
          let mut acc = 2;
          for key_val in object {
            acc += self.sizeof_key_val(key_val)? + 2;
          }
          Some(acc)
        }
      }
      Null(_) | Array(_) | Bool(_) | Float(_) | Int(_) | Object(_) | Str(_) => None,
    }
  }
}
fn indent(out: &mut String, indentation: u32) {
  out.push('\n');
  out.push_str(&"  ".repeat(indentation as usize));
}