Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
741a8e74
Commit
741a8e74
authored
4 years ago
by
Loïc Correnson
Browse files
Options
Downloads
Patches
Plain Diff
[dome] JSON decoders
parent
cda596fa
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
ivette/src/dome/src/renderer/data/json.ts
+165
-15
165 additions, 15 deletions
ivette/src/dome/src/renderer/data/json.ts
with
165 additions
and
15 deletions
ivette/src/dome/src/renderer/data/json.ts
+
165
−
15
View file @
741a8e74
...
...
@@ -5,7 +5,7 @@
import
{
DEVEL
}
from
'
dome/system
'
;
/**
Safe JSON utilities
Safe JSON utilities
.
@package dome/data/json
*/
...
...
@@ -32,16 +32,16 @@ export function parse(text: string, noError = false): json {
}
/**
Export JSON as a compact string.
Export JSON
(or any data)
as a compact string.
*/
export
function
stringify
(
js
:
json
)
{
export
function
stringify
(
js
:
any
)
{
return
JSON
.
stringify
(
js
,
undefined
,
0
);
}
/**
Export JSON as a string with indented content.
Export JSON
(or any data)
as a string with indented content.
*/
export
function
pretty
(
js
:
json
)
{
export
function
pretty
(
js
:
any
)
{
return
JSON
.
stringify
(
js
,
undefined
,
2
);
}
...
...
@@ -49,55 +49,105 @@ export function pretty(js: json) {
// --- SAFE Decoder
// --------------------------------------------------------------------------
/** Decoder for values of type `D`. */
export
type
Safe
<
D
>
=
(
js
:
json
)
=>
D
;
/**
Decode for values of type `D`, if any.
Same as `Safe<D | undefined>`.
*/
export
type
Loose
<
D
>
=
(
js
:
json
)
=>
D
|
undefined
;
export
type
Strict
<
D
>
=
(
js
:
json
)
=>
D
;
// --------------------------------------------------------------------------
// --- Primitives
// --------------------------------------------------------------------------
/** Primitive JSON number or `undefined`. */
export
const
jNumber
:
Loose
<
number
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
number
'
?
js
:
undefined
);
export
const
jZero
:
Strict
<
number
>
=
(
js
:
json
)
=>
(
/** Primitive JSON number or `0`. */
export
const
jZero
:
Safe
<
number
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
number
'
?
js
:
0
);
/** Primitive JSON boolean or `undefined`. */
export
const
jBoolean
:
Loose
<
boolean
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
boolean
'
?
js
:
undefined
);
export
const
jTrue
:
Strict
<
boolean
>
=
(
js
:
json
)
=>
(
/** Primitive JSON boolean or `true`. */
export
const
jTrue
:
Safe
<
boolean
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
boolean
'
?
js
:
true
);
export
const
jFalse
:
Strict
<
boolean
>
=
(
js
:
json
)
=>
(
/** Primitive JSON boolean or `false`. */
export
const
jFalse
:
Safe
<
boolean
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
boolean
'
?
js
:
false
);
/** Primitive JSON string or `undefined`. */
export
const
jString
:
Loose
<
string
>
=
(
js
:
json
)
=>
(
typeof
js
===
'
string
'
?
js
:
undefined
);
export
function
jEnum
(...
values
:
string
[]):
Loose
<
string
>
{
var
m
=
new
Map
<
string
,
string
>
();
/**
One of the enumerated _constants_ or `undefined`.
The typechecker will prevent you from listing values that are not in
type `A`. However, it will not protected you
from missings constants in `A`.
*/
export
function
jEnum
<
A
>
(...
values
:
((
string
|
number
)
&
A
)[]):
Loose
<
A
>
{
var
m
=
new
Map
<
string
|
number
,
A
>
();
values
.
forEach
(
v
=>
m
.
set
(
v
,
v
));
return
(
v
:
json
)
=>
(
typeof
v
===
'
string
'
?
m
.
get
(
v
)
:
undefined
);
}
/**
Refine a loose decoder with some default value.
The default value is returned when the provided JSON is `undefined` or
when the loose decoder returns `undefined`.
*/
export
function
jDefault
<
A
>
(
fn
:
Loose
<
A
>
,
defaultValue
:
A
,
):
S
trict
<
A
>
{
):
S
afe
<
A
>
{
return
(
js
:
json
)
=>
js
===
undefined
?
defaultValue
:
(
fn
(
js
)
??
defaultValue
);
}
export
function
jArray
<
A
>
(
fn
:
Strict
<
A
>
):
Strict
<
A
[]
>
{
/**
Force returning `undefined` or a default value for `undefined` JSON input.
Typically usefull to leverage an existing `Safe<A>` decoder.
*/
export
function
jOption
<
A
>
(
fn
:
Safe
<
A
>
,
defaultValue
?:
A
):
Loose
<
A
>
{
return
(
js
:
json
)
=>
(
js
===
undefined
?
defaultValue
:
fn
(
js
));
}
/**
Force returning `undefined` or a default value for `undefined` _or_ `null`
JSON input. Typically usefull to leverage an existing `Safe<A>` decoder.
*/
export
function
jNull
<
A
>
(
fn
:
Safe
<
A
>
,
defaultValue
?:
A
):
Loose
<
A
>
{
return
(
js
:
json
)
=>
(
js
===
undefined
||
js
===
null
?
defaultValue
:
fn
(
js
));
}
/**
Apply the decoder on each item of a JSON array, or return `[]` otherwize.
Can be also applied on a _loose_ decoder, but you will get
an array with possibly `undefined` elements. Use [[jList]]
to discard undefined elements, or use a true « safe » decoder.
*/
export
function
jArray
<
A
>
(
fn
:
Safe
<
A
>
):
Safe
<
A
[]
>
{
return
(
js
:
json
)
=>
Array
.
isArray
(
js
)
?
js
.
map
(
fn
)
:
[];
}
export
function
jList
<
A
>
(
fn
:
Loose
<
A
>
):
Strict
<
A
[]
>
{
/**
Apply the loose decoder on each item of a JSON array, discarding
all `undefined` elements. To keep all, possibly undefined array entries,
use [[jArray]] instead.
*/
export
function
jList
<
A
>
(
fn
:
Loose
<
A
>
):
Safe
<
A
[]
>
{
return
(
js
:
json
)
=>
{
const
buffer
:
A
[]
=
[];
if
(
Array
.
isArray
(
js
))
js
.
forEach
(
vj
=>
{
...
...
@@ -108,7 +158,107 @@ export function jList<A>(fn: Loose<A>): Strict<A[]> {
};
}
export
/** Apply a pair of decoders to JSON pairs, or return `undefined`. */
export
function
jPair
<
A
,
B
>
(
fa
:
Safe
<
A
>
,
fb
:
Safe
<
B
>
,
):
Loose
<
[
A
,
B
]
>
{
return
(
js
:
json
)
=>
Array
.
isArray
(
js
)
?
[
fa
(
js
[
0
]),
fb
(
js
[
1
]),
]
:
undefined
;
}
/** Similar to [[jPair]]. */
export
function
jTriple
<
A
,
B
,
C
>
(
fa
:
Safe
<
A
>
,
fb
:
Safe
<
B
>
,
fc
:
Safe
<
C
>
,
):
Loose
<
[
A
,
B
,
C
]
>
{
return
(
js
:
json
)
=>
Array
.
isArray
(
js
)
?
[
fa
(
js
[
0
]),
fb
(
js
[
1
]),
fc
(
js
[
2
]),
]
:
undefined
;
}
/** Similar to [[jPair]]. */
export
function
jTuple4
<
A
,
B
,
C
,
D
>
(
fa
:
Safe
<
A
>
,
fb
:
Safe
<
B
>
,
fc
:
Safe
<
C
>
,
fd
:
Safe
<
D
>
,
):
Loose
<
[
A
,
B
,
C
,
D
]
>
{
return
(
js
:
json
)
=>
Array
.
isArray
(
js
)
?
[
fa
(
js
[
0
]),
fb
(
js
[
1
]),
fc
(
js
[
2
]),
fd
(
js
[
3
]),
]
:
undefined
;
}
/** Similar to [[jPair]]. */
export
function
jTuple5
<
A
,
B
,
C
,
D
,
E
>
(
fa
:
Safe
<
A
>
,
fb
:
Safe
<
B
>
,
fc
:
Safe
<
C
>
,
fd
:
Safe
<
D
>
,
fe
:
Safe
<
E
>
,
):
Loose
<
[
A
,
B
,
C
,
D
,
E
]
>
{
return
(
js
:
json
)
=>
Array
.
isArray
(
js
)
?
[
fa
(
js
[
0
]),
fb
(
js
[
1
]),
fc
(
js
[
2
]),
fd
(
js
[
3
]),
fe
(
js
[
4
]),
]
:
undefined
;
}
/**
Decoders for each property of object type `A`.
Optional fields in `A` can be assigned a loose decoder.
*/
export
type
Props
<
A
>
=
{
[
P
in
keyof
A
]:
Safe
<
A
[
P
]
>
;
}
/**
Decode an object given the decoders of its fields.
Returns `undefined` for non-object JSON.
*/
export
function
jObject
<
A
>
(
fp
:
Props
<
A
>
):
Loose
<
A
>
{
return
(
js
:
json
)
=>
{
if
(
js
!==
null
&&
typeof
js
===
'
object
'
&&
!
Array
.
isArray
(
js
))
{
const
buffer
=
{}
as
A
;
for
(
var
k
of
Object
.
keys
(
fp
))
{
const
fn
=
fp
[
k
as
keyof
A
];
const
fv
=
fn
(
js
[
k
]);
buffer
[
k
as
keyof
A
]
=
fv
;
}
return
buffer
;
}
return
undefined
;
};
}
/** Type of dictionaries. */
export
type
dict
<
A
>
=
{
[
key
:
string
]:
A
};
/**
Decode a JSON dictionary, dicarding all inconsistent entries.
If the JSON contains no valid entry, still returns `{}`.
*/
export
function
jDictionary
<
A
>
(
fn
:
Loose
<
A
>
):
Safe
<
dict
<
A
>>
{
return
(
js
:
json
)
=>
{
const
buffer
:
dict
<
A
>
=
{};
if
(
js
!==
null
&&
typeof
js
===
'
object
'
&&
!
Array
.
isArray
(
js
))
{
for
(
var
k
of
Object
.
keys
(
js
))
{
const
fv
=
fn
(
js
[
k
]);
if
(
fv
)
buffer
[
k
]
=
fv
;
}
}
return
buffer
;
};
}
// --------------------------------------------------------------------------
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment