1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Keeping the recursion of the JSON-LD algorithms off the caller's native
//! stack.
//!
//! Context conversion, the Context Processing algorithm, Expansion and
//! Compaction all recurse once per nesting level of their input. An embedder
//! may run them on a thread whose stack it has already partly used, such as a
//! Tokio worker deep inside a request handler, so the recursion depth alone
//! cannot decide whether the thread's stack suffices.
//!
//! A synchronous recursion point runs its callee through
//! [`on_sufficient_stack`]. An `async` one wraps its callee in [`Recursion`]:
//! boxing a recursive call moves the callee's *state* to the heap but not its
//! *polling*, because a parent polls its child from inside its own `poll`, so
//! the native stack still deepens by one set of poll frames per level. Either
//! way, when less than [`RED_ZONE`] of the current stack is left, the callee
//! runs on a freshly allocated segment of [`SEGMENT`] bytes instead. Whatever
//! bounds a recursion stays what bounds it; this only guarantees the bound is
//! reached on any thread.
use ;
/// Stack left below which a recursion level moves to a fresh segment.
///
/// The value `jstrict` uses, so one red zone governs every recursion over a
/// document, from parsing and printing its JSON to the JSON-LD algorithms.
pub const RED_ZONE: usize = RED_ZONE;
/// Size of each fresh stack segment.
pub const SEGMENT: usize = SEGMENT;
/// Runs `callee`, on a fresh stack segment when the current one is nearly used.
///
/// Delegates to [`jstrict::native_stack::on_sufficient_stack`].
/// A recursive call of an `async` algorithm.
///
/// The callee lives on the heap, like a `Box::pin` of it would, and every poll
/// of it runs through [`on_sufficient_stack`], so polling a chain of nested
/// calls cannot exhaust the native stack.
;