///|
pub(all) enum Js {
Nl
Bl(Bool)
Nu(Double)
St(String)
Ar(Array[Js])
Ob(Map[String, Js])
} derive(Debug)
///|
fn emp(v : Js, o : Bool) -> Bool {
match v {
Nl => true
St(s) => s == ""
Nu(n) => o && n == 0.0
Ar(a) => a.is_empty()
Ob(m) => m.is_empty()
Bl(_) => false
}
}
///|
fn d(v : Js, o : Bool, depth : Int) -> Js {
if depth <= 0 {
v
} else {
match v {
Ar(a) => {
let m = a.map(fn(i) { d(i, o, depth - 1) })
let f = m.filter(fn(i) { !emp(i, o) })
if f.is_empty() {
Nl
} else {
Ar(f)
}
}
Ob(m) => {
let new_map : Map[String, Js] = Map([], capacity=8)
for k, val in m {
let c = d(val, o, depth - 1)
if !emp(c, o) {
new_map[k] = c
}
}
if new_map.is_empty() {
Nl
} else {
Ob(new_map)
}
}
_ => v
}
}
}
///|
pub fn strip(v : Js, oz : Bool) -> Js {
let c = d(v, oz, 1000)
match c {
Nl => Ob(Map([], capacity=0))
Ob(m) if m.is_empty() => Ob(Map([], capacity=0))
Ob(_) => c
_ => Ob(Map([], capacity=0))
}
}
///|
fn is_null(v : Js) -> Bool {
match v {
Nl => true
_ => false
}
}
///|
pub fn strip_null(v : Js) -> Js {
match v {
Ar(a) => {
let mapped = a.map(fn(x) { strip_null(x) })
Ar(mapped.filter(fn(x) { !is_null(x) }))
}
Ob(m) => {
let new_m : Map[String, Js] = Map([], capacity=8)
for k, val in m {
let c = strip_null(val)
if !is_null(c) {
new_m[k] = c
}
}
Ob(new_m)
}
_ => v
}
}
///|
pub fn strip_empty(v : Js) -> Js {
d(v, false, 1000)
}