///|
fn json_get(obj : Map[String, Json], key : String) -> Json? {
obj.get(key)
}
///|
fn json_required(
obj : Map[String, Json],
key : String,
) -> Result[Json, SourceMapError] {
match json_get(obj, key) {
Some(value) => Ok(value)
None => Err(MissingField(field=key))
}
}
///|
fn decode_string_field(
obj : Map[String, Json],
key : String,
) -> Result[String?, SourceMapError] {
match json_get(obj, key) {
None | Some(Null) => Ok(None)
Some(String(value)) => Ok(Some(value))
Some(_) => Err(JsonDecode(path=key, expected="string or null"))
}
}
///|
fn decode_int_field_required(
obj : Map[String, Json],
key : String,
) -> Result[Int, SourceMapError] {
match json_required(obj, key) {
Ok(Number(value, ..)) => Ok(value.to_int())
Ok(_) => Err(JsonDecode(path=key, expected="integer"))
Err(err) => Err(err)
}
}
///|
fn decode_string_array_required(
obj : Map[String, Json],
key : String,
) -> Result[Array[String], SourceMapError] {
match json_required(obj, key) {
Ok(Array(items)) => {
let out : Array[String] = []
for i, item in items {
match item {
String(value) => out.push(value)
_ => return Err(JsonDecode(path="\{key}[\{i}]", expected="string"))
}
}
Ok(out)
}
Ok(_) => Err(JsonDecode(path=key, expected="array of strings"))
Err(err) => Err(err)
}
}
///|
fn decode_optional_string_array(
obj : Map[String, Json],
key : String,
) -> Result[Array[String?], SourceMapError] {
match json_get(obj, key) {
None => Ok([])
Some(Array(items)) => {
let out : Array[String?] = []
for i, item in items {
match item {
Null => out.push(None)
String(value) => out.push(Some(value))
_ =>
return Err(
JsonDecode(path="\{key}[\{i}]", expected="string or null"),
)
}
}
Ok(out)
}
Some(_) => Err(JsonDecode(path=key, expected="array of strings or nulls"))
}
}
///|
fn decode_int_array_optional(
obj : Map[String, Json],
key : String,
) -> Result[Array[Int], SourceMapError] {
match json_get(obj, key) {
None => Ok([])
Some(Array(items)) => {
let out : Array[Int] = []
for i, item in items {
match item {
Number(value, ..) => out.push(value.to_int())
_ => return Err(JsonDecode(path="\{key}[\{i}]", expected="integer"))
}
}
Ok(out)
}
Some(_) => Err(JsonDecode(path=key, expected="array of integers"))
}
}
///|
fn decode_mappings_required(
obj : Map[String, Json],
) -> Result[Array[MappingSegment], SourceMapError] {
match json_required(obj, "mappings") {
Ok(String(raw)) => decode_mappings(raw)
Ok(_) => Err(JsonDecode(path="mappings", expected="VLQ mappings string"))
Err(err) => Err(err)
}
}
///|
pub fn SourceMap::from_json(json : Json) -> Result[SourceMap, SourceMapError] {
match json {
Object(obj) => {
let version = match decode_int_field_required(obj, "version") {
Ok(value) => value
Err(err) => return Err(err)
}
let sources = match decode_string_array_required(obj, "sources") {
Ok(value) => value
Err(err) => return Err(err)
}
let names = match decode_string_array_required(obj, "names") {
Ok(value) => value
Err(err) => return Err(err)
}
let mappings = match decode_mappings_required(obj) {
Ok(value) => value
Err(err) => return Err(err)
}
let file = match decode_string_field(obj, "file") {
Ok(value) => value
Err(err) => return Err(err)
}
let source_root = match decode_string_field(obj, "sourceRoot") {
Ok(value) => value
Err(err) => return Err(err)
}
let sources_content = match
decode_optional_string_array(obj, "sourcesContent") {
Ok(value) => value
Err(err) => return Err(err)
}
let ignore_list = match decode_int_array_optional(obj, "ignoreList") {
Ok(value) => value
Err(err) => return Err(err)
}
Ok({
version,
file,
source_root,
sources,
sources_content,
names,
mappings,
ignore_list,
})
}
_ => Err(JsonDecode(path="root", expected="object"))
}
}
///|
pub fn SourceMap::from_json_string(
text : StringView,
) -> Result[SourceMap, SourceMapError] {
let json = @json.parse(text) catch {
err => return Err(JsonParse(message=err.to_string()))
}
SourceMap::from_json(json)
}
///|
fn string_array_json(items : ArrayView[String]) -> Json {
Json::array(items.map(item => Json::string(item)))
}
///|
fn optional_string_array_json(items : ArrayView[String?]) -> Json {
Json::array(
items.map(item => {
match item {
Some(value) => Json::string(value)
None => null
}
}),
)
}
///|
fn int_array_json(items : ArrayView[Int]) -> Json {
Json::array(items.map(item => Json::number(item.to_double())))
}
///|
pub fn SourceMap::to_json(self : SourceMap) -> Json {
let obj : Map[String, Json] = Map([])
obj["version"] = Json::number(self.version.to_double())
if self.file is Some(file) {
obj["file"] = Json::string(file)
}
if self.source_root is Some(root) {
obj["sourceRoot"] = Json::string(root)
}
obj["sources"] = string_array_json(self.sources)
if self.sources_content.length() > 0 {
obj["sourcesContent"] = optional_string_array_json(self.sources_content)
}
obj["names"] = string_array_json(self.names)
obj["mappings"] = Json::string(self.encoded_mappings())
if self.ignore_list.length() > 0 {
obj["ignoreList"] = int_array_json(self.ignore_list)
}
Json::object(obj)
}
///|
pub fn SourceMap::to_json_string(self : SourceMap, indent? : Int = 0) -> String {
self.to_json().stringify(indent~)
}