git.delta.rocks / jrsonnet / refs/commits / d44593872785

difftreelog

refactor(evaluator) extract json to module

Lach2020-08-15parent: #219ced5.patch.diff
in: master

4 files changed

addedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
2pub use stdlib::*;2pub use stdlib::*;
33
4pub mod format;4pub mod format;
5pub mod manifest;
56
modifiedcrates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 builtin::format::{format_arr, format_obj},2 builtin::{
3 format::{format_arr, format_obj},
4 manifest::{escape_string_json, manifest_json_ex, ManifestJsonOptions, ManifestType},
5 },
3 context_creator, equals,6 context_creator, equals,
4 error::Error::*,7 error::Error::*,
5 escape_string_json, future_wrapper, lazy_val, manifest_json_ex, parse_args, primitive_equals,8 future_wrapper, lazy_val, parse_args, primitive_equals, push, throw, with_state, Context,
6 push, throw,
7 val::ManifestJsonOptions,
8 with_state, Context, ContextCreator, FuncDesc, LazyBinding, LazyVal, LocError, ManifestType,9 ContextCreator, FuncDesc, LazyBinding, LazyVal, LocError, ObjMember, ObjValue, Result, Val,
9 ObjMember, ObjValue, Result, Val, ValType,10 ValType,
10};11};
11use closure::closure;12use closure::closure;
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 builtin::manifest::{manifest_json_ex, ManifestJsonOptions, ManifestType},
2 error::Error::*,3 error::Error::*,
3 evaluate,4 evaluate,
4 function::{parse_function_call, parse_function_call_map, place_args},5 function::{parse_function_call, parse_function_call_map, place_args},
354 }355 }
355}356}
356
357#[derive(PartialEq)]
358pub enum ManifestType {
359 // Applied in manifestification
360 Manifest,
361 /// Used for std.manifestJson
362 /// Empty array/objects extends to "[\n\n]" instead of "[ ]" as in manifest
363 Std,
364 // No line breaks, used in `obj+''`
365 ToString,
366}
367
368pub struct ManifestJsonOptions<'s> {
369 pub padding: &'s str,
370 pub mtype: ManifestType,
371}
372
373pub fn manifest_json_ex(val: &Val, options: &ManifestJsonOptions<'_>) -> Result<String> {
374 let mut out = String::new();
375 manifest_json_ex_buf(val, &mut out, &mut String::new(), options)?;
376 Ok(out)
377}
378fn manifest_json_ex_buf(
379 val: &Val,
380 buf: &mut String,
381 cur_padding: &mut String,
382 options: &ManifestJsonOptions<'_>,
383) -> Result<()> {
384 use std::fmt::Write;
385 match val.unwrap_if_lazy()? {
386 Val::Bool(v) => {
387 if v {
388 buf.push_str("true");
389 } else {
390 buf.push_str("false");
391 }
392 }
393 Val::Null => buf.push_str("null"),
394 Val::Str(s) => buf.push_str(&escape_string_json(&s)),
395 Val::Num(n) => write!(buf, "{}", n).unwrap(),
396 Val::Arr(items) => {
397 buf.push('[');
398 if !items.is_empty() {
399 if options.mtype != ManifestType::ToString {
400 buf.push('\n');
401 }
402
403 let old_len = cur_padding.len();
404 cur_padding.push_str(options.padding);
405 for (i, item) in items.iter().enumerate() {
406 if i != 0 {
407 buf.push(',');
408 if options.mtype == ManifestType::ToString {
409 buf.push(' ');
410 } else {
411 buf.push('\n');
412 }
413 }
414 buf.push_str(cur_padding);
415 manifest_json_ex_buf(item, buf, cur_padding, options)?;
416 }
417 cur_padding.truncate(old_len);
418
419 if options.mtype != ManifestType::ToString {
420 buf.push('\n');
421 buf.push_str(cur_padding);
422 }
423 } else if options.mtype == ManifestType::Std {
424 buf.push_str("\n\n");
425 buf.push_str(cur_padding);
426 } else if options.mtype == ManifestType::ToString {
427 buf.push(' ');
428 }
429 buf.push(']');
430 }
431 Val::Obj(obj) => {
432 buf.push('{');
433 let fields = obj.visible_fields();
434 if !fields.is_empty() {
435 if options.mtype != ManifestType::ToString {
436 buf.push('\n');
437 }
438
439 let old_len = cur_padding.len();
440 cur_padding.push_str(options.padding);
441 for (i, field) in fields.into_iter().enumerate() {
442 if i != 0 {
443 buf.push(',');
444 if options.mtype == ManifestType::ToString {
445 buf.push(' ');
446 } else {
447 buf.push('\n');
448 }
449 }
450 buf.push_str(cur_padding);
451 buf.push_str(&escape_string_json(&field));
452 buf.push_str(": ");
453 manifest_json_ex_buf(&obj.get(field)?.unwrap(), buf, cur_padding, options)?;
454 }
455 cur_padding.truncate(old_len);
456
457 if options.mtype != ManifestType::ToString {
458 buf.push('\n');
459 buf.push_str(cur_padding);
460 }
461 } else if options.mtype == ManifestType::Std {
462 buf.push_str("\n\n");
463 buf.push_str(cur_padding);
464 } else if options.mtype == ManifestType::ToString {
465 buf.push(' ');
466 }
467 buf.push('}');
468 }
469 Val::Func(_) | Val::Intristic(_, _) => {
470 throw!(RuntimeError("tried to manifest function".into()))
471 }
472 Val::Lazy(_) => unreachable!(),
473 };
474 Ok(())
475}
476pub fn escape_string_json(s: &str) -> String {
477 use std::fmt::Write;
478 let mut out = String::new();
479 out.push('"');
480 for c in s.chars() {
481 match c {
482 '"' => out.push_str("\\\""),
483 '\\' => out.push_str("\\\\"),
484 '\u{0008}' => out.push_str("\\b"),
485 '\u{000c}' => out.push_str("\\f"),
486 '\n' => out.push_str("\\n"),
487 '\r' => out.push_str("\\r"),
488 '\t' => out.push_str("\\t"),
489 c if c < 32 as char || (c >= 127 as char && c <= 159 as char) => {
490 write!(out, "\\u{:04x}", c as u32).unwrap()
491 }
492 c => out.push(c),
493 }
494 }
495 out.push('"');
496 out
497}
498
499#[test]
500fn json_test() {
501 assert_eq!(escape_string_json("\u{001f}"), "\"\\u001f\"")
502}
503357