on master help sign in
Merge branch 'urbit:master' into add-dist-docs
commitabacd5079b5ce97a9ea5420890b63f093c98971b authortinnus-napbus <77721746+tinnus-napbus@users.noreply.github.com> dateTue 5 Oct 2021, 23:04 (5 years ago) parent51beeddf36fddd
40 files changed+6295−442
components/Footer.js+1−1 components/Header.js+7 content/docs/arvo/ames/_index.md+20 content/docs/arvo/ames/ames-api.md−292 content/docs/arvo/ames/cryptography.md+3−3 content/docs/arvo/ames/data-types.md+389 content/docs/arvo/ames/scry.md+126 content/docs/arvo/ames/tasks.md+193 content/docs/arvo/clay/architecture.md+12−88 content/docs/arvo/clay/clay.md+4−1 content/docs/arvo/clay/marks/_index.md+23 content/docs/arvo/clay/marks/examples.md+248 content/docs/arvo/clay/marks/marks.md+59 content/docs/arvo/clay/marks/using-marks.md+240 content/docs/arvo/clay/marks/writing-marks.md+333 content/docs/hoon/reference/_index.md+6−3 content/docs/hoon/reference/rune/ket.md+12−3 content/docs/hoon/reference/stdlib/2b.md+37 content/docs/hoon/reference/zuse/2d_1-5.md+587 content/docs/hoon/reference/zuse/2d_6.md+1551 content/docs/hoon/reference/zuse/2d_7.md+1307 content/docs/hoon/reference/zuse/2e_2-3.md+67 content/docs/hoon/reference/zuse/_index.md+31 content/docs/hoon/reference/zuse/table-of-contents.md+247 content/getting-started/_index.md+9 content/getting-started/planet.md+1−1 content/grants/cypherscope-bot.md+80 content/grants/network-explorer-data-pipeline-http-api.md+2−2 content/grants/overhaul-the-urbitorg-website.md+2−2 content/grants/static-site-generation.md+7−29 content/grants/urbian-a-customized-linux-distribution-for-urbit-appliances.md+1−1 content/grants/urbit-event-series.md+1−1 content/using/_index.md+3−3 content/using/os/_index.md+1−1 content/using/os/getting-started.md → content/using/os/basics.md+1−1 content/using/os/dist-faq.md+76−3 lib/glossary.js+596 pages/index.js+4−4 pages/using/[[...slug]].js+3−3 vercel.json+5
components/Footer.js+1−1
@@ -17,7 +17,7 @@ export default function Footer() {
1717 </Link>
1818 <Link href="/using">
1919 <div>
20− <a className="type-bold text-wall-500">Operator's Manual</a>
20+ <a className="type-bold text-wall-500">User's Manual</a>
2121 </div>
2222 </Link>
2323 <Link href="https://github.com/urbit/port/releases">
components/Header.js+7
@@ -72,6 +72,13 @@ export default function Header(props) {
7272 >
7373 Docs
7474 </ActiveLink>
75+ <ActiveLink
76+ currentPath={currentPath}
77+ className="mr-5 type-ui"
78+ href="/using"
79+ >
80+ Manual
81+ </ActiveLink>
7582 <ActiveLink
7683 currentPath={currentPath}
7784 className="mr-5 type-ui"
content/docs/arvo/ames/_index.md+20
@@ -5,3 +5,23 @@ sort_by = "weight"
55template = "sections/docs/chapters.html"
66insert_anchor_links = "right"
77+++
8+
9+## [Overview](/docs/arvo/ames/ames)
10+
11+An overview of Ames and its capabilities.
12+
13+## [Cryptography](/docs/arvo/ames/cryptography)
14+
15+A technical overview of how Ames implements cryptography.
16+
17+## [API Reference](/docs/arvo/ames/tasks)
18+
19+The `task`s Ames takes and the `gift`s it returns.
20+
21+## [Scry Reference](/docs/arvo/ames/scry)
22+
23+The scry endpoints of Ames.
24+
25+## [Data Types](/docs/arvo/ames/data-types)
26+
27+Reference documentation of the various data types used by Ames.
content/docs/arvo/ames/ames-api.mddeleted−292
@@ -1,292 +0,0 @@
1−+++
2−title = "API Reference"
3−weight = 10
4−template = "doc.html"
5−+++
6−
7−In this document we describe the public interface for Ames. Namely, we describe
8−each `task` that Ames can be `%pass`ed, and which `gift`(s) Ames can `%give` in return.
9−
10−Some `task`s appear to have more than one arm associated to them, e.g. there are
11−four `+on-hear` arms. We denote this where it occurs, but always refer to the
12−`on-hear:event-core` arm.
13−
14−Ames `task`s can be naturally divided into two categories: messaging tasks and
15−system/lifecycle tasks.
16−
17−## Messaging Tasks
18−
19−### `%hear`
20−
21−`%hear` handles raw packet receipt. This `task` only ever originates from Unix.
22−It does the initial processing of a packet, namely by passing the raw packet
23−information to `+decode-packet` which deserializes the packet and giving that data and the origin of the
24−packet to `+on-hear-packet`, which begins the transformation of the packet into
25−a new event in the form of a `+event-core`.
26−
27−There are multiple `+on-hear` arms in `ames.hoon`. Here we refer to
28−`on-hear:event-core`, as that is the one called by a `%hear` `task`. The other ones are used
29−primarily for ack and nack processing, or receiving message fragments.
30−
31−#### Accepts
32−
33−```hoon
34−[=lane =blob]
35−```
36−
37−`%hear` takes in a `blob`, which is essentially a large atom (around 1kB or less)
38−that is the raw data of the message, and a `lane`, which is the origin of the
39−message (typically an IP address).
40−
41−#### Returns
42−
43−`%hear` can trigger a number of possible returns. It can trigger the release of
44−zero or more additional packets via `%send` `gift`s. It may also trigger a `%boon`
45−or `%plea` `gift` (collectively referred to as a `%memo` within Ames) to a local vane in the case of a completed message.
46−
47−
48−### `%heed`
49−
50−A vane can pass Ames a `%heed` `task` to request Ames track a peer's
51−responsiveness. If our `%boon`s to it start backing up locally,
52−Ames will `give` a `%clog` back to the requesting vane containing the
53−unresponsive peer's Urbit address.
54−
55−Stop tracking a peer by sending Ames a
56−`%jilt` `task`.
57−
58−
59−#### Accepts
60−
61−```hoon
62−=ship
63−```
64−
65−The ship to be tracked.
66−
67−#### Returns
68−
69−If the `ship` is indeed being unresponsive, as measured by backed up `%boon`s,
70−Ames will `give` a `%clog` `gift` to the requesting vane containing the
71−unresponsive peer's urbit address.
72−
73−
74−### `%hole`
75−
76−`%hole` handles packet crash notification. `%hole` works much like `%hear`, in
77−that it passes an incoming raw packet to `+decode-packet` to be deserialized,
78−and then passes that data along with the source of the packet to
79−`+on-hear-packet` along with a `?` set to `%.n` denoting that there is something wrong with
80−the packet.
81−
82−#### Accepts
83−
84−```hoon
85−[=lane =blob]
86−```
87−`%hole` takes in a `blob`, which is essentially a large atom (around 1kB or less)
88−that is the raw data of the message, and a `lane`, which is the origin of the
89−message (typically an IP address).
90−
91−#### Returns
92−
93−Like `%hear`, `%hole` can trigger additional packets in the form of `%send`
94−`gift`s, and may also yield a `%boon` or `%plea` `gift` to a local vane.
95−
96−
97−### `%jilt`
98−
99−`%jilt` stops tracking a potentially unresponsive peer that was previously being
100−tracked as a result of the `%heed` `task`.
101−
102−There are two `+on-jilt` arms, this `task` utilizes `on-hear:event-core`.
103−
104−#### Accepts
105−
106−```hoon
107−=ship
108−```
109−
110−The `ship` we no longer wish to track.
111−
112−#### Returns
113−
114−This `task` returns no `gift`s.
115−
116−
117−### `%plea`
118−
119−`%plea` is the `task` used to instruct Ames to send a message. It extends the
120−`%pass`/`%give` semantics across the network. As such, it is the most
121−fundamental `task` in Ames and the primary reason for its existence.
122−
123−Ames also `pass`es a `%plea` `note` to another vane when it receives a message on a
124−"forward flow" from a peer, originally passed from one of the peer's vanes to the
125−peer's Ames.
126−
127−Ultimately `%plea` causes `%send` `gift`(s) to be sent to Unix, which tells
128−Unix to send packets. In terms of `%pass`/`%give` semantics, this is in
129−response to the `%born` `task`, which came along the Unix `duct`, rather than a
130−response to the `%plea`.
131−
132−#### Accepts
133−
134−```hoon
135−[=ship =plea]
136−```
137−
138−A `%plea` `task` takes in the `ship` the `plea` is addressed to, and a `$plea`,
139−which is
140−
141−```hoon
142− +$ plea [vane=@tas =path payload=*]
143−```
144−Here, `vane` is the destination vane on the remote ship, `path` is the internal
145−route on the receiving ship, and `payload` is the semantic message content.
146−
147−#### Returns
148−
149−This `task` returns no `gift`s.
150−
151−## System and Lifecycle Tasks
152−
153−### `%born`
154−
155−Each time you start your Urbit, the Arvo kernel calls the `%born` task for Ames.
156−
157−#### Accepts
158−
159−`%born` takes no arguments.
160−
161−#### Returns
162−
163−In response to a `%born` `task`, Ames `%give`s Jael a `%turf` `gift`.
164−
165−The `duct` along which `%born` comes is Ames' only duct to Unix, so `%send`
166−`gift`s (which are instructions for Unix to send a packet) are also returned in
167−response to `%born`.
168−
169−
170−### `%crud`
171−
172−`%crud` is called whenever an error involving Ames occurs. It produces a crash
173−report in response.
174−
175−#### Accepts
176−
177−```hoon
178−=error
179−```
180−
181−A `$error` is a `[tag=@tas =tang]`.
182−
183−#### Returns
184−
185−Ames does not `give` a `gift` in response to a `%crud` `task`, but it does
186−`%pass` Dill a `%flog` `task` instructing it to print `error`.
187−
188−
189−## `%init`
190−
191−`%init` is called a single time during the very first boot process, immediately
192−after the [larval stage](/docs/arvo/overview#larval-stage-core)
193−is completed. This initializes the vane. Jael is initialized first, followed by
194−other vanes such as Ames.
195−
196−In response to receiving the `%init` `task`, Ames subscribes to the information
197−contained by Jael.
198−
199−#### Accepts
200−
201−```hoon
202−our=ship
203−```
204−
205−`%init` takes in the name of our ship, which is a `@p`.
206−
207−#### Returns
208−
209−```hoon
210− =~ (emit duct %pass /turf %j %turf ~)
211− (emit duct %pass /private-keys %j %private-keys ~)
212−```
213−
214−`%init` sends two moves that subscribe to `%turf` and `%private-keys` in Jael.
215−
216−
217−### `%sift`
218−
219−This `task` filters debug output by ship.
220−
221−#### Accepts
222−
223−```hoon
224−ships=(list ship)
225−```
226−
227−The list of ships for which debug output is desired.
228−
229−#### Returns
230−
231−This `task` returns no `gift`s.
232−
233−
234−### `%spew`
235−
236−Sets verbosity toggles on debug output. These toggles are as follows.
237−
238−* `%snd` - sending packets
239−* `%rcv` - receiving packets
240−* `%odd` - unusual events
241−* `%msg` - message-level events
242−* `%ges` - congestion control
243−* `%for` - packet forwarding
244−* `%rot` - routing attempts
245−
246−Each toggle is a flag set to `%.n` by default.
247−
248−#### Accepts
249−
250−```hoon
251−verbs=(list verb)
252−```
253−
254−`%spew` takes in a `list` of `verb`, which are verbosity flags for Ames.
255−
256−```hoon
257−+$ verb ?(%snd %rcv %odd %msg %ges %for %rot)
258−```
259−
260−`%spew` flips each toggle given in `verbs`.
261−
262−#### Returns
263−
264−This `task` returns no `gift`s.
265−
266−
267−### `%vega`
268−
269−`%vega` is called whenever the kernel is updated. Ames currently does not do
270−anything in response to this.
271−
272−#### Accepts
273−
274−`%vega` takes no arguments.
275−
276−#### Returns
277−
278−This `task` returns no `gift`s.
279−
280−
281−### `%wegh`
282−
283−This `task` is a request to Ames to produce a memory usage report.
284−
285−#### Accepts
286−
287−This `task` has no arguments.
288−
289−#### Returns
290−
291−In response to this `task,` Ames `%give`s a `%mass` `gift` containing Ames'
292−current memory usage.
content/docs/arvo/ames/cryptography.md+3−3
@@ -1,6 +1,6 @@
11+++
22title = "Cryptography"
3−weight = 5
3+weight = 2
44template = "doc.html"
55+++
66
@@ -34,7 +34,7 @@ Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algori
3434is used for authentication
3535
3636The encrypted payload of each packet is a `$shut-packet`, which is the `+jam` of
37−a cell with the `bone`, message number, and message fragment or ack (see
37+a cell with the [$bone](/docs/arvo/ames/data-types#bone), message number, and message fragment or ack (see
3838[Ames](/docs/arvo/ames/ames) for more information on packet structure). The
3939message fragment is signed using the authentication key. It is encrypted using
4040[`+en:crub:crypto`](/docs/arvo/reference/cryptography#en) found in
@@ -43,7 +43,7 @@ message fragment is signed using the authentication key. It is encrypted using
4343## Diffie-Hellman key exchange {#key-exchange}
4444
4545For each foreign ship a given ship has communicated with, `$ames-state` contains a
46−`$peer-state`, inside which the `$symmetric-key` (an atom which nests under
46+[$peer-state](/docs/arvo/ames/data-types#peer-state), inside which the [$symmetric-key](/docs/arvo/ames/data-types#symmetric-key) (an atom which nests under
4747`@uw`) is utilized for encrypting all Ames packets shared between the two ships.
4848The `symmetric-key` is derived using [`+shar:ed:crypto`](/docs/arvo/reference/cryptography#ed) found in `sys/zuse.hoon`,
4949which is an arm utilized for generating the symmetric key for elliptic curve
content/docs/arvo/ames/data-types.mdnew file+389
@@ -0,0 +1,389 @@
1++++
2+title = "Data Types"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+Here are the data types used by Ames, as defined in `lull.hoon`.
8+
9+## `$address`
10+
11+```hoon
12++$ address @uxaddress
13+```
14+
15+Opaque atomic transport address to or from Unix. For Ames over UDP, it will encode the IP address and port.
16+
17+## `$verb`
18+
19+```hoon
20++$ verb ?(%snd %rcv %odd %msg %ges %for %rot)
21+```
22+
23+Verbosity flag for Ames. Use with `|ames-verb %flag1 %flag2 ...` and turn off with `|ames-verb`.
24+
25+- `%snd` - Sending packets.
26+- `%rcv` - Receiving packets.
27+- `%odd` - Unusual events.
28+- `%msg` - Message-level events.
29+- `%ges` - Congestion control.
30+- `%for` - Packet forwarding.
31+- `%rot` - Routing attempts.
32+
33+## `$blob`
34+
35+```hoon
36++$ blob @uxblob
37+```
38+
39+Raw atom to or from Unix, representing a packet.
40+
41+## `$error`
42+
43+```hoon
44++$ error [tag=@tas =tang]
45+```
46+
47+Tagged diagnostic trace.
48+
49+## `$lane`
50+
51+```hoon
52++$ lane (each @pC address)
53+```
54+
55+Ship transport address; either opaque [$address](#address) or galaxy. The runtime knows how to look up galaxies, so we don't need to know their transport addresses.
56+
57+## `$plea`
58+
59+```hoon
60++$ plea [vane=@tas =path payload=*]
61+```
62+
63+Application-level message, as a `%pass`.
64+
65+- `vane` - Destination vane on remote ship.
66+- `path` - Internal route on the receiving ship.
67+- `payload` - Semantic message contents.
68+
69+## `$bone`
70+
71+```hoon
72++$ bone @udbone
73+```
74+
75+Message flow index - mapped to `duct`s in the [$ossuary](#ossuary).
76+
77+The first `bone` is 0. They increment by 4, since each flow includes a bit for each message determining forward vs. backward and a second bit for whether the message is on the normal flow or the associated diagnostic flow (for naxplanations).
78+
79+The least significant bit of a `bone` is:
80+
81+- 1 if "forward", i.e. we send `%plea`s on this flow.
82+- 0 if "backward", i.e. we receive `%plea`s on this flow.
83+
84+The second-least significant bit is 1 if the `bone` is a naxplanation `bone`, and 0 otherwise. Only naxplanation messages can be sent on a naxplanation `bone`, as `%boon`s.
85+
86+## `$fragment`
87+
88+```hoon
89++$ fragment @uwfragment
90+```
91+
92+A message fragment.
93+
94+## `$fragment-num`
95+
96+```hoon
97++$ fragment-num @udfragmentnum
98+```
99+
100+Message fragment count.
101+
102+## `$message-blob`
103+
104+```hoon
105++$ message-blob @udmessageblob
106+```
107+
108+Unfragmented message blob.
109+
110+## `$message-num`
111+
112+```hoon
113++$ message-num @udmessagenum
114+```
115+
116+Message count.
117+
118+## `$public-key`
119+
120+```hoon
121++$ public-key @uwpublickey
122+```
123+
124+A peer's public key.
125+
126+## `$symmetric-key`
127+
128+```hoon
129++$ symmetric-key @uwsymmetrickey
130+```
131+
132+A symmetric key for encrypting messages to a peer. This is produced by performing an elliptic curve Diffie-Hellman using our private key and the peer's public key.
133+
134+## `$ack`
135+
136+```hoon
137++$ ack
138+ $% [%ok ~]
139+ [%nack ~]
140+ [%naxplanation =error]
141+ ==
142+```
143+
144+A message acknowledgement.
145+
146+- `%ok` - Positive acknowledgement.
147+- `%nack` - Negative acknowledgement.
148+- `%naxplanation` - Nack trace.
149+
150+## `$ship-state`
151+
152+```hoon
153++$ ship-state
154+ $% [%alien alien-agenda]
155+ [%known peer-state]
156+ ==
157+```
158+
159+All Ames knows about a peer.
160+
161+- `%alien` - No PKI data, so enqueue actions to perform once we learn it.
162+- `%known` - We know their `life` and public keys, so we have a channel.
163+
164+## `$alien-agenda`
165+
166+```hoon
167++$ alien-agenda
168+ $: messages=(list [=duct =plea])
169+ packets=(set =blob)
170+ heeds=(set duct)
171+ ==
172+```
173+
174+What to do when Ames learns a peer's life and keys.
175+
176+- `messages` - [$plea](#plea)s local vanes have asked Ames to send.
177+- `packets` - Packets we've tried to send.
178+- `heeds` - Local tracking requests; passed through into [$peer-state](#peer-state).
179+
180+## `$peer-state`
181+
182+```hoon
183++$ peer-state
184+ $: $: =symmetric-key
185+ =life
186+ =public-key
187+ sponsor=ship
188+ ==
189+ route=(unit [direct=? =lane])
190+ =qos
191+ =ossuary
192+ snd=(map bone message-pump-state)
193+ rcv=(map bone message-sink-state)
194+ nax=(set [=bone =message-num])
195+ heeds=(set duct)
196+ ==
197+```
198+
199+State for a peer with known life and keys.
200+
201+- `route` - Transport-layer destination for packets to the peer.
202+- `qos` - Quality of service; connection status to the peer.
203+- `ossuary` - [$bone](#bone) to `duct` mapper.
204+- `snd` - Per-`bone` message pumps to send messages as fragments.
205+- `rcv` - Per-`bone` message sinks to assemble messages from fragments.
206+- `nax` - Unprocessed nacks (negative acknowledgments).
207+- `heeds` - Listeners for `%clog` notifications.
208+
209+## `$qos`
210+
211+```hoon
212++$ qos
213+ $~ [%unborn *@da]
214+ [?(%live %dead %unborn) last-contact=@da]
215+```
216+
217+Quality of service; how is the connection to a peer doing?
218+
219+- `%live` - Peer is ok.
220+- `%dead` - Peer is not responding.
221+- `%unborn` - Peer is sunken.
222+- `last-contact` - Last time Ames heard from the peer, or if `%unborn`, the time when we first started tracking then.
223+
224+## `$ossuary`
225+
226+```hoon
227++$ ossuary
228+ $: =next=bone
229+ by-duct=(map duct bone)
230+ by-bone=(map bone duct)
231+ ==
232+```
233+
234+[$bone](#bone) to `duct` mapping, `next` is the next `bone` to map to a `duct`.
235+
236+## `$message-pump-state`
237+
238+```hoon
239++$ message-pump-state
240+ $: current=_`message-num`1
241+ next=_`message-num`1
242+ unsent-messages=(qeu message-blob)
243+ unsent-fragments=(list static-fragment)
244+ queued-message-acks=(map message-num ack)
245+ =packet-pump-state
246+ ==
247+```
248+
249+Persistent state for a `|message-pump`.
250+
251+- `current`- Sequence number of earliest message sent or being sent.
252+- `next` - Sequence number of next message to send.
253+- `unsent-messages` - Messages to be sent after current message.
254+- `unsent-fragments` - Fragments of current message waiting for sending.
255+- `queued-message-acks` - Future message acks to be applied after current.
256+- `packet-pump-state` - State of corresponding `|packet-pump`.
257+
258+## `$static-fragment`
259+
260+```hoon
261++$ static-fragment
262+ $: =message-num
263+ num-fragments=fragment-num
264+ =fragment-num
265+ =fragment
266+ ==
267+```
268+
269+A packet; a fragment of a message and metadata.
270+
271+## `$packet-pump-state`
272+
273+```hoon
274++$ packet-pump-state
275+ $: next-wake=(unit @da)
276+ live=(tree [live-packet-key live-packet-val])
277+ metrics=pump-metrics
278+ ==
279+```
280+
281+Persistent state for a `|packet-pump`.
282+
283+- `next-wake` - Last timer we've set, or null.
284+- `live` - Packets in flight; sent but not yet acked.
285+- `metrics` - Congestion control information.
286+
287+## `$pump-metrics`
288+
289+```hoon
290++$ pump-metrics
291+ $: rto=_~s1
292+ rtt=_~s1
293+ rttvar=_~s1
294+ ssthresh=_10.000
295+ cwnd=_1
296+ num-live=@ud
297+ counter=@ud
298+ ==
299+```
300+
301+Congestion control state for a `|packet-pump`.
302+
303+- `rto` - Retransmission timeout.
304+- `rtt` - Roundtrip time estimate, low-passed using EWMA.
305+- `rttvar` - Mean deviation of `rtt`, also low-passed with EWMA.
306+- `num-live` - How many packets sent, awaiting ack.
307+- `ssthresh` - Slow-start threshold.
308+- `cwnd` - Congestion window; max unacked packets.
309+
310+## `$live-packet`
311+
312+```hoon
313++$ live-packet
314+ $: key=live-packet-key
315+ val=live-packet-val
316+ ==
317+```
318+
319+A packet in flight, as tracked in the [$packet-pump-state](#packet-pump-state).
320+
321+## `$live-packet-key`
322+
323+```hoon
324++$ live-packet-key
325+ $: =message-num
326+ =fragment-num
327+ ==
328+```
329+
330+Identifier of a packet in flight.
331+
332+## `$live-packet-val`
333+
334+```hoon
335++$ live-packet-val
336+ $: packet-state
337+ num-fragments=fragment-num
338+ =fragment
339+ ==
340+```
341+
342+Content and metadata about a packet in flight.
343+
344+## `$packet-state`
345+
346+```hoon
347++$ packet-state
348+ $: last-sent=@da
349+ retries=@ud
350+ skips=@ud
351+ ==
352+```
353+
354+Sending statistics about a packet in flight.
355+
356+## `$message-sink-state`
357+
358+```hoon
359++$ message-sink-state
360+ $: last-acked=message-num
361+ last-heard=message-num
362+ pending-vane-ack=(qeu [=message-num message=*])
363+ live-messages=(map message-num partial-rcv-message)
364+ nax=(set message-num)
365+ ==
366+```
367+
368+State of a `|message-sink` to assemble received messages.
369+
370+- `last-acked` - Highest [$message-num](#message-num) Ames has fully acknowledged.
371+- `last-heard` - Highest `message-num` Ames has heard all fragments for.
372+- `pending-vane-ack` - Heard but not processed by local vane.
373+- `live-messages` - Partially received messages.
374+
375+## `$partial-rcv-message`
376+
377+```hoon
378++$ partial-rcv-message
379+ $: num-fragments=fragment-num
380+ num-received=fragment-num
381+ fragments=(map fragment-num fragment)
382+ ==
383+```
384+
385+A message for which Ames has received some fragments.
386+
387+- `num-fragments` - Total number of fragments in the message.
388+- `num-received` - How many fragments Ames has received so far.
389+- `fragments` - The received fragments themselves.
content/docs/arvo/ames/scry.mdnew file+126
@@ -0,0 +1,126 @@
1++++
2+title = "Scry Reference"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+Here are the scry endpoints of Ames. All of them take a `%x` `care` and require the `desk` in the path prefix be empty, so the general format is `.^([type] %ax /=//=/[some-path])`.
8+
9+## /protocol/version
10+
11+A scry with a `%x` `care` and a `path` of `/protocol/version` will return the current Ames protocol version as a `@`.
12+
13+#### Example
14+
15+```
16+> .^(@ %ax /=//=/protocol/version)
17+0
18+```
19+
20+## /peers
21+
22+A scry with a `%x` `care` and a `path` of `/peers` will return all ships that Ames is aware of. The type returned is a `(map ship ?(%alien %known))`, where `%known` means we have PKI data for them and `%alien` means we don't.
23+
24+#### Example
25+
26+```
27+> .^((map ship ?(%alien %known)) %ax /=//=/peers)
28+{[p=~wet q=%known] [p=~nes q=%known]}
29+```
30+
31+## /peers/[ship]
32+
33+A scry with a `%x` `care` and a `path` of `/peers/[ship]` where `[ship]` is a ship name like `~dopzod` will return everything Ames knows about that ship, or crash if the ship is unknown to Ames. The type returned is a [$ship-state](/docs/arvo/ames/data-types#ship-state).
34+
35+#### Example
36+
37+```
38+> .^(ship-state:ames %ax /=//=/peers/~nes)
39+[ %known
40+ [ symmetric-key=0wEF.5-Mp4.ehBxk.a-ktl.CAUHq.~XNVq.AfPFk.TwBbj.rc7MS
41+ life=1
42+ public-key=0w9R.IG6Km.CQfuL.lP9Da.l~kh1.lOHzV.xactk.1ybiB.hekW~.VC2d0.DDRsU.h6GHl.PKmRX.p3u2-.vO4Hg.QTOlp.A4AI0.uGPVy
43+ sponsor=~nes
44+ ]
45+ route=[~ [direct=%.y lane=[%.y p=~nes]]]
46+ qos=[%dead last-contact=~2021.8.9..16.11.36..fdbc]
47+ ossuary
48+ [ next-bone=4
49+ by-duct={[p=~[/gall/sys/way/~nes/hood /gall/use/hood/0w2.4d7EV/out/~nes/hood/helm/hi/~nes /dill //term/1] q=0]}
50+ by-bone={[p=0 q=~[/gall/sys/way/~nes/hood /gall/use/hood/0w2.4d7EV/out/~nes/hood/helm/hi/~nes /dill //term/1]]}
51+ ]
52+ snd
53+ { [ p=0
54+ q
55+ [ current=2
56+ next=3
57+ unsent-messages={}
58+ unsent-fragments=~
59+ queued-message-acks={}
60+ packet-pump-state
61+ [ next-wake=[~ ~2021.8.17..02.21.14..3d23]
62+ live={[[message-num=2 fragment-num=0] [last-sent=~2021.8.17..02.19.14..3d23 retries=2.255 skips=0] num-fragments=1 fragment=0w2.QJ1qS.JzaQn.w7rMp.IzuTJ.7M7aP.-1s~1]}
63+ metrics=[rto=~m2 rtt=~s1 rttvar=~s1 ssthresh=1 cwnd=1 num-live=1 counter=1]
64+ ]
65+ ]
66+ ]
67+ }
68+ rcv={}
69+ nax={}
70+ heeds={~[/gall/sys/lag /dill //term/1]}
71+]
72+```
73+
74+## /peers/[ship]/forward-lane
75+
76+A scry with a `%x` `care` and a `path` of `/peers/[ship]/forward-lane` where `[ship]` is a ship name like `~dopzod` will return outbound routes to the given ship, or `~` if there are none. The type returned is a `(list lane:ames)`, see [$lane](/docs/arvo/ames/data-types#lane) for type details.
77+
78+#### Examples
79+
80+```
81+> .^((list lane:ames) %ax /=//=/peers/~nes/forward-lane)
82+~[[%.y p=~nes]]
83+```
84+
85+```
86+> .^((list lane:ames) %ax /=//=/peers/~nec/forward-lane)
87+~
88+```
89+
90+## /bones/[ship]
91+
92+A scry with a `%x` `care` and a `path` of `/bones/[ship]` where `[ship]` is a ship name like `~dopzod` will return inbound and outbound [$bone](/docs/arvo/ames/data-types#bone)s, which index message flows. If the ship in question is unknown to Ames, the scry will fail. The type returned is `[snd=(set bone) rcv=(set bone)]`.
93+
94+#### Example
95+
96+```
97+> .^([snd=(set bone) rcv=(set bone)] %ax /=//=/bones/~nes)
98+[snd={0} rcv={}]
99+```
100+
101+## /snd-bones/[ship]/[bone]
102+
103+A scry with a `%x` `care` and a `path` of `/snd-bones/[ship]/[bone]`, where `[ship]` is a ship name like `~dopzod` and `[bone]` is an outbound [$bone](/docs/arvo/ames/data-types#bone), will return message flow details for that `bone`. If the ship in question is unknown to Ames or the `bone` does not exist, the scry will fail. The type returned is a [$message-pump-state](/docs/arvo/ames/data-types#message-pump-state) wrapped in a `vase`.
104+
105+#### Example
106+
107+```
108+> !< message-pump-state:ames .^(vase %ax /=//=/snd-bones/~nes/0)
109+[ current=2
110+ next=3
111+ unsent-messages={}
112+ unsent-fragments=~
113+ queued-message-acks={}
114+ packet-pump-state
115+ [ next-wake=[~ ~2021.8.17..02.27.14..aaff]
116+ live
117+ { [ [message-num=2 fragment-num=0]
118+ [last-sent=~2021.8.17..02.25.14..aaff retries=2.258 skips=0]
119+ num-fragments=1
120+ fragment=0w2.QJ1qS.JzaQn.w7rMp.IzuTJ.7M7aP.-1s~1
121+ ]
122+ }
123+ metrics=[rto=~m2 rtt=~s1 rttvar=~s1 ssthresh=1 cwnd=1 num-live=1 counter=1]
124+ ]
125+]
126+```
content/docs/arvo/ames/tasks.mdnew file+193
@@ -0,0 +1,193 @@
1++++
2+title = "API Reference"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+In this document we describe the public interface for Ames. Namely, we describe
8+each `task` that Ames can be `%pass`ed, and which `gift`(s) Ames can `%give` in return.
9+
10+Some `task`s appear to have more than one arm associated to them, e.g. there are
11+four `+on-hear` arms. We denote this where it occurs, but always refer to the
12+`+on-hear:event-core` arm.
13+
14+Ames `task`s can be naturally divided into two categories: messaging tasks and
15+system/lifecycle tasks.
16+
17+## Messaging Tasks
18+
19+### `%hear`
20+
21+```hoon
22+[%hear =lane =blob]
23+```
24+
25+`%hear` handles raw packet receipt.
26+
27+This `task` only ever originates from Unix. It does the initial processing of a packet, namely by passing the raw packet information to `+decode-packet` which deserializes the packet and giving that data and the origin of the packet to `+on-hear-packet`, which begins the transformation of the packet into a new event in the form of a `+event-core`.
28+
29+There are multiple `+on-hear` arms in `ames.hoon`. Here we refer to `+on-hear:event-core`, as that is the one called by a `%hear` `task`. The other ones are used primarily for ack and nack processing, or receiving message fragments.
30+
31+`%hear` takes in a [$blob](/docs/arvo/ames/data-types#blob), which is essentially a large atom (around 1kB or less) that is the raw data of the message, and a [$lane](/docs/arvo/ames/data-types#lane), which is the origin of the message (typically an IP address).
32+
33+#### Returns
34+
35+`%hear` can trigger a number of possible returns. It can trigger the release of zero or more additional packets via `%send` `gift`s. It may also trigger a `%boon` or `%plea` `gift` (collectively referred to as a `%memo` within Ames) to a local vane in the case of a completed message.
36+
37+### `%heed`
38+
39+```hoon
40+[%heed =ship]
41+```
42+
43+A vane can pass Ames a `%heed` `task` to request Ames track a peer's responsiveness. If our `%boon`s to it start backing up locally, Ames will `give` a `%clog` back to the requesting vane containing the unresponsive peer's Urbit address.
44+
45+Stop tracking a peer by sending Ames a [%jilt](#jilt) `task`.
46+
47+The `ship` field specifies the peer to be tracked.
48+
49+#### Returns
50+
51+If the `ship` is indeed being unresponsive, as measured by backed up `%boon`s,
52+Ames will `give` a `%clog` `gift` to the requesting vane containing the
53+unresponsive peer's urbit address.
54+
55+### `%jilt`
56+
57+```hoon
58+[%jilt =ship]
59+```
60+
61+`%jilt` stops tracking a potentially unresponsive peer that was previously being
62+tracked as a result of the [%heed](#heed) `task`.
63+
64+There are two `+on-jilt` arms, this `task` utilizes `+on-hear:event-core`.
65+
66+The `ship` field specifies the peer we want to stop tracking.
67+
68+#### Returns
69+
70+This `task` returns no `gift`s.
71+
72+### `%plea`
73+
74+```hoon
75+[%plea =ship =plea:ames]
76+```
77+
78+`%plea` is the `task` used to instruct Ames to send a message. It extends the
79+`%pass`/`%give` semantics across the network. As such, it is the most
80+fundamental `task` in Ames and the primary reason for its existence.
81+
82+Ames also `pass`es a `%plea` `note` to another vane when it receives a message on a
83+"forward flow" from a peer, originally passed from one of the peer's vanes to the
84+peer's Ames.
85+
86+Ultimately `%plea` causes `%send` `gift`(s) to be sent to Unix, which tells
87+Unix to send packets. In terms of `%pass`/`%give` semantics, this is in
88+response to the `%born` `task`, which came along the Unix `duct`, rather than a
89+response to the `%plea`.
90+
91+A `%plea` `task` takes in the `ship` the `plea` is addressed to, and a [$plea](/docs/arvo/ames/data-types.md#plea).
92+
93+#### Returns
94+
95+This `task` returns no `gift`s.
96+
97+## System Tasks
98+
99+### `%born`
100+
101+```hoon
102+[%born ~]
103+```
104+
105+Each time you start your Urbit, the Arvo kernel calls the `%born` `task` for Ames.
106+
107+#### Returns
108+
109+In response to a `%born` `task`, Ames `%give`s Jael a `%turf` `gift`.
110+
111+The `duct` along which `%born` comes is Ames' only duct to Unix, so `%send`
112+`gift`s (which are instructions for Unix to send a packet) are also returned in
113+response to `%born`.
114+
115+### `%init`
116+
117+```hoon
118+[%init ~]
119+```
120+
121+`%init` is called a single time during the very first boot process, immediately
122+after the [larval stage](/docs/arvo/overview#larval-stage-core)
123+is completed. This initializes the vane. Jael is initialized first, followed by
124+other vanes such as Ames.
125+
126+In response to receiving the `%init` `task`, Ames subscribes to the information
127+contained by Jael.
128+
129+#### Returns
130+
131+```hoon
132+=~ (emit duct %pass /turf %j %turf ~)
133+ (emit duct %pass /private-keys %j %private-keys ~)
134+```
135+
136+`%init` sends two moves that subscribe to `%turf` and `%private-keys` in Jael.
137+
138+### `%sift`
139+
140+```hoon
141+[%sift ships=(list ship)]
142+```
143+
144+This `task` filters debug output by ship. This `task` is used internally when the `|ames-sift` `hood` generator is run from the dojo.
145+
146+The `ships` field specifies the ships for which debug output is desired.
147+
148+#### Returns
149+
150+This `task` returns no `gift`s.
151+
152+### `%spew`
153+
154+```hoon
155+[%spew veb=(list verb)]
156+```
157+
158+Sets verbosity toggles on debug output. This `task` is used internally when the `|ames-verb` `hood` generator is run from the dojo.
159+
160+`%spew` takes in a `list` of [$verb](/docs/arvo/ames/data-types#verb), which are verbosity flags for Ames.
161+
162+`%spew` flips each toggle given in `veb`.
163+
164+#### Returns
165+
166+This `task` returns no `gift`s.
167+
168+### `%stir`
169+
170+```hoon
171+[%stir arg=@t]
172+```
173+
174+A `%stir` `task` starts timers for any flows that lack them.
175+
176+The `arg` field is unused.
177+
178+#### Returns
179+
180+This `task` returns no `gift`s.
181+
182+### `%vega`
183+
184+```hoon
185+[%vega ~]
186+```
187+
188+`%vega` is called whenever the kernel is updated. Ames currently does not do
189+anything in response to this.
190+
191+#### Returns
192+
193+This `task` returns no `gift`s.
content/docs/arvo/clay/architecture.md+12−88
@@ -23,7 +23,7 @@ state is persistent.
2323In a more traditional OS, everything in RAM can be erased at any
2424time by power failure, and is always erased on reboot. Thus, a
2525primary purpose of a filesystem is to ensure files persist across
26−power failures and reboots. In Arvo, both power failures and
26+power failures and reboots. In Arvo, both power failures and
2727reboots are special cases of suspending computation, which is
2828done safely since our event log is already persistent. Therefore,
2929Clay is not needed in Arvo for persistence. Why, then, do we have a
@@ -37,7 +37,7 @@ tree. It is easy and intuitive to read from and write to a
3737filesystem tree.
3838
3939Second, Clay has a distributed revision-control system baked into
40−it. Traditional filesystems are not revision controlled, so
40+it. Traditional filesystems are not revision controlled, so
4141userspace software -- such as git -- is written on top of them to
4242do so. Clay natively provides the same functionality as modern
4343DVCSes, and more.
@@ -101,25 +101,25 @@ the topmost commit is always numbered, and every numbered commit
101101is an ancestor of every later numbered commit.
102102
103103There are three ways to refer to particular commits in the
104−revision history. Firstly, one can use the revision number.
104+revision history. Firstly, one can use the revision number.
105105Secondly, one can use any absolute time between the one numbered
106106commit and the next (inclusive of the first, exclusive of the
107107second). Thirdly, every `desk` has a `map` of labels to revision
108108numbers. These labels may be used to refer to specific commits.
109109
110110Additionally, Clay is a global filesystem, so data on other urbits
111−is easily accessible the same way as data on our local urbit. In
111+is easily accessible the same way as data on our local urbit. In
112112general, the path to a particular revision of a `desk` is
113−`/~urbit-name/desk-name/revision`. Thus, to get `/try/readme/md`
113+`/~urbit-name/desk-name/revision`. Thus, to get `/try/readme/md`
114114from revision 5 of the home `desk` on `~sampel-sipnym`, we refer to
115−`/~sampel-sipnym/home/5/try/readme/md`. Clay's namespace is thus
115+`/~sampel-sipnym/home/5/try/readme/md`. Clay's namespace is thus
116116global and referentially transparent.
117117
118118### A Typed Filesystem
119119
120120Since Clay is a general filesystem for storing data of arbitrary
121121types, in order to revision control correctly it needs to be
122−aware of types all the way through. Traditional revision control
122+aware of types all the way through. Traditional revision control
123123does an excellent job of handling source code, so for source code
124124we act very similar to traditional revision control. The
125125challenge is to handle other data similarly well.
@@ -145,7 +145,7 @@ branches and merged at will.
145145Suppose Alice is tasked with touching up a picture, improving the
146146color balance, adjusting the contrast, and so forth, while Bob
147147has the job of cropping the picture to fit where it's needed and
148−adding textual overlay. Without type-aware revision control,
148+adding textual overlay. Without type-aware revision control,
149149these changes must be made serially, requiring Alice and Bob to
150150explicitly coordinate their efforts. With type-aware revision
151151control, these operations may be performed in parallel, and then
@@ -168,87 +168,11 @@ different sentences may be flagged as a conflict. In general,
168168prose should be diffed by sentence, not by line.
169169
170170As far as we are aware, Clay is the first generalized,
171−type-aware revision control system. We'll go into the workings
171+type-aware revision control system. We'll go into the workings
172172of this system in some detail.
173173
174174### Marks
175175
176−Central to a typed filesystem is the idea of types. In Clay, we
177−call these `mark`s. A `mark` is a file that defines a type,
178−conversion routines to and from the `mark`, and diff, patch, and
179−merge routines.
180−
181−For example, a `%txt` mark may be a list of lines of text, and it
182−may include conversions to `%mime` to allow it to be serialized
183−and sent to a browser or to the Unix filesystem. It will also
184−include Hunt-McIlroy diff, patch, and merge algorithms.
185−
186−A `%json` `mark` would be defined as a JSON object in the code, and
187−it would have a parser to convert from `%txt` and a printer to
188−convert back to `%txt`. The diff, patch, and merge algorithms are
189−fairly straightforward for JSON, though they're very different
190−from the text ones.
191−
192−More formally, a `mark` is a core with three [arms](/docs/glossary/arm/): `+grab`,
193−`+grow`, and `+grad`. In `+grab` is a series of functions to
194−convert from other `mark`s to the given `mark`. In `+grow` is a
195−series of functions to convert from the given `mark` to other
196−`mark`s. In `+grad` is `+diff`, `+pact`, `+join`, and `+mash`, and
197−`+form`.
198−
199−The types are as follows, in an informal pseudocode:
200−
201−```
202− ++ grab:
203− ++ mime: <mime> -> <mark-type>
204− ++ txt: <txt> -> <mark-type>
205− ...
206− ++ grow:
207− ++ mime: <mark-type> -> <mime>
208− ++ txt: <mark-type> -> <txt>
209− ...
210− ++ grad
211− ++ form: <mark-type>
212− ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
213− ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
214− ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
215− ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
216−```
217−
218−These types are basically what you would expect. Not every `mark`
219−has each of these functions defined -- all of them are optional
220−in the general case.
221−
222−In general, for a particular `mark`, the `+grab` and `+grow` entries
223−(if they exist) should be inverses of each other.
224−
225−In `+grad`, `+diff` takes two instances of a `mark` and produces a diff of them
226−whose `mark` is given by `+form`. `+pact` takes an instance of a `mark` and
227−patches it with the given diff. `+join` takes two diffs and attempts to merge
228−them into a single diff. If there are conflicts, it produces null. `+mash` takes
229−two diffs and forces a merge, annotating any conflicts.
230−
231−In general, if `+diff` called with A and B produces diff D, then
232−`+pact` called with A and D should produce B. Also, if `+join`
233−of two diffs does not produce null, then `+mash` of the same
234−diffs should produce the same result.
235−
236−Alternately, instead of `+diff`, `+pact`, `+join`, and
237−`+mash`, a `mark` can provide the same functionality by defining
238−`+grad` to be the name of another `mark` to which we wish to
239−delegate the revision control responsibilities. Then, before
240−running any of those functions, Clay will convert to the other
241−`mark`, and convert back afterward. For example, the `%hoon` `mark`
242−is revision-controlled in the same way as `%txt`, so its `+grad`
243−is simply `++ grad %txt`. Of course, `+txt` must be defined in
244−`+grow` and `+grab` as well.
245−
246−Every file in Clay has a `mark`, and that `mark` must have a
247−fully-functioning `+grad`. `Mark`s are used for more than just
248−Clay, and other `mark`s don't need a `+grad`, but if a piece of
249−data is to be saved to Clay, we must know how to revision-control
250−it.
251−
252−Additionally, if a file is to be synced out to Unix, then it must
253−have conversion routines to and from the `%mime` `mark`.
254−
176+Central to a typed filesystem is the idea of file types. In Clay, we
177+call these `mark`s. See the [Marks](/docs/arvo/clay/marks/marks)
178+section for more details.
content/docs/arvo/clay/clay.md+4−1
@@ -5,7 +5,6 @@ template = "doc.html"
55aliases = ["/docs/learn/arvo/clay/"]
66+++
77
8−
98Our filesystem.
109
1110`%clay` is version-controlled, referentially-transparent, and global.
@@ -56,3 +55,7 @@ Details of the various `task`s you can use to interact with Clay.
5655[Examples](/docs/arvo/clay/examples)
5756
5857Example usage of the various Clay `task`s.
58+
59+[Marks](/docs/arvo/clay/marks/marks)
60+
61+Details of `mark`s as well as a guide to writing them and their usage.
content/docs/arvo/clay/marks/_index.mdnew file+23
@@ -0,0 +1,23 @@
1++++
2+title = "Marks"
3+weight = 10
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6+insert_anchor_links = "right"
7++++
8+
9+[Overview](/docs/arvo/clay/marks/marks)
10+
11+Overview of `mark`s.
12+
13+[Writing Marks](/docs/arvo/clay/marks/writing-marks)
14+
15+A practical walk-through of writing a `mark` file.
16+
17+[Using Marks](/docs/arvo/clay/marks/using-marks)
18+
19+Details of using `mark` conversion gates and `mark` cores in your own code.
20+
21+[Examples](/docs/arvo/clay/marks/examples)
22+
23+The example code used in the Writing Marks guide.
content/docs/arvo/clay/marks/examples.mdnew file+248
@@ -0,0 +1,248 @@
1++++
2+title = "Examples"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+These are the files used in the [Writing Marks](/docs/arvo/clay/marks/writing-marks) guide.
8+
9+## `/lib/csv/hoon`
10+
11+```hoon
12+|%
13+++ validate :: All rows same length?
14+ |= csv=(list (list @t))
15+ ^- ?
16+ =/ result
17+ %+ roll csv
18+ |= [row=(list @t) =flag ref=(unit @ud)]
19+ ?. flag
20+ [flag ref]
21+ ?~ ref
22+ [flag `(lent row)]
23+ ?. =(u.ref (lent row))
24+ [%.n ref]
25+ [flag ref]
26+ flag.result
27+++ en-csv :: csv -> atom (to mime)
28+ |= csv=(list (list @t))
29+ |^ ^- @t
30+ (cat 3 (crip (join '\0a' (turn csv en-row))) '\0a')
31+ ++ en-row :: encode row
32+ |= row=(list @t)
33+ ^- @t
34+ (crip (join ',' (turn row en-field)))
35+ ++ en-field :: encode field
36+ |= field=@t
37+ ^- @t
38+ %+ rash
39+ field
40+ %+ cook
41+ |= =tape
42+ ^- @t
43+ ?~ tape ''
44+ ?: =('"' i.tape)
45+ (cat 3 (crip tape) '"')
46+ (crip tape)
47+ ;~ pose
48+ (full (star ;~(less (mask "\",\0a\0d") next)))
49+ ;~ plug
50+ (easy '"')
51+ (star ;~(pose (cold '""' doq) next))
52+ ==
53+ ==
54+ --
55+++ de-csv :: atom -> csv (from mime)
56+ |= dat=@t
57+ |^ ^- (list (list @t))
58+ =/ parsed (parse dat)
59+ ?. (validate parsed)
60+ ~|(%mixed-col-count !!)
61+ parsed
62+ ++ parse :: parse cord
63+ |= dat=@t
64+ |^ ^- (list (list @t))
65+ %+ rash
66+ dat
67+ %+ most
68+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
69+ (most com parse-field)
70+ ++ parse-field :: parse field from cord
71+ |^
72+ %+ cook
73+ |=(a=tape (crip a))
74+ ;~(pose unenclosed enclosed)
75+ ++ unenclosed :: unquoted field
76+ ;~ sfix
77+ (star ;~(less (mask "\",\0a\0d") next))
78+ ;~ pose
79+ ;~ plug
80+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
81+ ;~(less next (easy ~))
82+ ==
83+ ;~(less doq (easy ~))
84+ ==
85+ ==
86+ ++ enclosed :: quoted field
87+ |^
88+ ;~ sfix
89+ (ifix [prefix suffix] content)
90+ ;~ pose
91+ ;~(simu (mask ",\0a\0d") (easy ~))
92+ ;~ plug
93+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
94+ ;~(less next (easy ~))
95+ ==
96+ ;~(less next (easy ~))
97+ ==
98+ ==
99+ ++ content :: quoted field contents
100+ %- star
101+ ;~ pose
102+ (cold '"' (jest '""'))
103+ %+ cold '\0a'
104+ ;~(pose (jest '\0d\0a') (just '\0d'))
105+ ;~(less doq next)
106+ ==
107+ ++ prefix ;~(pose ;~(plug (star ace) doq) doq) :: quoted field prefix
108+ ++ suffix ;~(pose ;~(plug doq (star ace)) doq) :: quoted field suffix
109+ --
110+ --
111+ --
112+ --
113+++ csv-join
114+ |= [ali=(urge:clay (list @t)) bob=(urge:clay (list @t))]
115+ ^- (unit (urge:clay (list @t)))
116+ |^
117+ =. ali (clean ali)
118+ =. bob (clean bob)
119+ |- ^- (unit (urge:clay (list @t)))
120+ ?~ ali `bob
121+ ?~ bob `ali
122+ ?- -.i.ali
123+ %&
124+ ?- -.i.bob
125+ %&
126+ ?: =(p.i.ali p.i.bob)
127+ %+ bind $(ali t.ali, bob t.bob)
128+ |=(cud=(urge:clay (list @t)) [i.ali cud])
129+ ?: (gth p.i.ali p.i.bob)
130+ %+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)
131+ |=(cud=(urge:clay (list @t)) [i.bob cud])
132+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))
133+ |=(cud=(urge:clay (list @t)) [i.ali cud])
134+ ::
135+ %|
136+ ?: =(p.i.ali (lent p.i.bob))
137+ %+ bind $(ali t.ali, bob t.bob)
138+ |=(cud=(urge:clay (list @t)) [i.bob cud])
139+ ?: (gth p.i.ali (lent p.i.bob))
140+ %+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)
141+ |=(cud=(urge:clay (list @t)) [i.bob cud])
142+ ~
143+ ==
144+ ::
145+ %|
146+ ?- -.i.bob
147+ %|
148+ ?. =(i.ali i.bob)
149+ ~
150+ %+ bind $(ali t.ali, bob t.bob)
151+ |=(cud=(urge:clay (list @t)) [i.ali cud])
152+ ::
153+ %&
154+ ?: =(p.i.bob (lent p.i.ali))
155+ %+ bind $(ali t.ali, bob t.bob)
156+ |=(cud=(urge:clay (list @t)) [i.ali cud])
157+ ?: (gth p.i.bob (lent p.i.ali))
158+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))
159+ |=(cud=(urge:clay (list @t)) [i.ali cud])
160+ ~
161+ ==
162+ ==
163+ ++ clean :: clean
164+ |= wig=(urge:clay (list @t))
165+ ^- (urge:clay (list @t))
166+ ?~ wig ~
167+ ?~ t.wig wig
168+ ?: ?=(%& -.i.wig)
169+ ?: ?=(%& -.i.t.wig)
170+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
171+ [i.wig $(wig t.wig)]
172+ ?: ?=(%| -.i.t.wig)
173+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
174+ [i.wig $(wig t.wig)]
175+ --
176+--
177+```
178+
179+## `/mar/csv/hoon`
180+
181+```hoon
182+/+ *csv
183+|_ csv=(list (list @t))
184+++ grab
185+ |%
186+ ++ mime |=((pair mite octs) (de-csv q.q))
187+ ++ noun
188+ |= n=*
189+ ^- (list (list @t))
190+ =/ result ((list (list @t)) n)
191+ ?> (validate result)
192+ result
193+ --
194+++ grow
195+ |%
196+ ++ mime
197+ ?> (validate csv)
198+ [/text/csv (as-octs:mimes:html (en-csv csv))]
199+ ++ noun
200+ ?> (validate csv)
201+ csv
202+ --
203+++ grad
204+ |%
205+ ++ form %csv-diff
206+ ++ diff
207+ |= bob=(list (list @t))
208+ ^- (urge:clay (list @t))
209+ ?> (validate csv)
210+ ?> (validate bob)
211+ (lusk:differ csv bob (loss:differ csv bob))
212+ ++ pact
213+ |= dif=(urge:clay (list @t))
214+ ^- (list (list @t))
215+ =/ result (lurk:differ csv dif)
216+ ?> (validate result)
217+ result
218+ ++ join
219+ |= $: ali=(urge:clay (list @t))
220+ bob=(urge:clay (list @t))
221+ ==
222+ ^- (unit (urge:clay (list @t)))
223+ (csv-join ali bob)
224+ ++ mash
225+ |= $: [ship desk (urge:clay (list @t))]
226+ [ship desk (urge:clay (list @t))]
227+ ==
228+ ^- (urge:clay (list @t))
229+ ~|(%csv-mash !!)
230+ --
231+--
232+```
233+
234+## `/mar/csv-diff/hoon`
235+
236+```hoon
237+|_ dif=(urge:clay (list @t))
238+++ grab
239+ |%
240+ ++ noun (urge:clay (list @t))
241+ --
242+++ grow
243+ |%
244+ ++ noun dif
245+ --
246+++ grad %noun
247+--
248+```
content/docs/arvo/clay/marks/marks.mdnew file+59
@@ -0,0 +1,59 @@
1++++
2+title = "Overview"
3+weight = 1
4+template = "doc.html"
5++++
6+
7+Clay is a typed filesystem, and we call these file types `mark`s. When talking about Hoon and Arvo we'll often talk of types like `@ud`, `(list @t)`, etc. A `mark` will specify such a type for its files, but it does more than just that - it also defines conversion routines to and from other `mark`s, as well as diff, patch, and merge routines.
8+
9+For example, a `%txt` `mark` defines the type of a `%txt` file as a `wain` (a `(list @t)`). It defines a conversion function to a `%mime` `mark` to allow it to be serialized and sent to a browser or to the Unix filesystem. It also includes Hunt-McIlroy diff, patch, and merge algorithms. Conversion functions will be different for different `mark`s, as will things like diff algorithms. An image file like a `%png`, for example, just replaces the old blob of data with the new one rather than implementing a complex binary diff and patch algorithm, so how these functions are implemented depends on the file type and use case.
10+
11+`mark` files are stored in the `/mar` directory. The `path` of the `%txt` `mark`, for example, is `/mar/txt/hoon`.
12+
13+A `mark` is a door (a core with a sample) with three arms: `+grab`, `+grow`, and `+grad`. The door's sample defines its type. In `+grab` is a series of functions to convert from other `mark`s to the given `mark`. In `+grow` is a series of functions to convert from the given `mark` to other `mark`s. In `+grad` is `+diff`, `+pact`, `+join`, `+mash`, and `+form`.
14+
15+Here's its basic structure in an informal pseudocode:
16+
17+```
18+|_ <mark-type>
19+++ grab:
20+ ++ noun: <noun> -> <mark-type>
21+ ++ mime: <mime> -> <mark-type>
22+ ++ txt: <txt> -> <mark-type>
23+ ...
24+++ grow:
25+ ++ noun: <mark-type> -> <noun>
26+ ++ mime: <mark-type> -> <mime>
27+ ++ txt: <mark-type> -> <txt>
28+ ...
29+++ grad
30+ ++ form: <diff-mark>
31+ ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
32+ ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
33+ ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
34+ ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
35+```
36+
37+These types are basically what you would expect. In `+grab`, only a `+noun` arm is mandatory, the rest are optional. The `+grow` arm itself is optional, as are any arms within it. In `+grad`, all arms are mandatory unless revision control is delegated to another `mark`, which we'll discuss later.
38+
39+In general, for a particular `mark`, the `+grab` and `+grow` entries should be inverses of each other. They needn't be symmetrical though - you may want to be able to convert from your `mark` to `%json` but not from `%json` to your `mark`, for example.
40+
41+In `+grad`, `+diff` takes two instances of a `mark` and produces a diff of them whose `mark` is given by `+form`. `+pact` takes an instance of a `mark` and patches it with the given diff. In general, if `+diff` called with A and B produces diff D, then `+pact` called with A and D should produce B.
42+
43+`+join` takes two diffs and attempts to merge them into a single diff. If there are conflicts, it produces null. `+mash` takes two diffs and forces a merge, even if there are conflicts. How your `+mash` function force-merges conflicting diffs is up to you. The `%txt` `mark` annotates any conflicts, for example, but there may be other ways. If `+join` of two diffs does not produce null, then `+mash` of the same diffs should produce the same result. Note that `+mash` is not used by Clay in its ordinary filesystem operations, so you may wish to leave it as a dummy arm that crashes if called.
44+
45+Alternately, instead of `+form`, `+diff`, `+pact`, `+join`, and `+mash`, a `mark` can provide the same functionality by defining `+grad` to be the name of another `mark` to which we wish to delegate the revision control responsibilities. Then, before running any of those functions, Clay will convert to the other `mark`, and convert back afterward. For example, the `%hoon` `mark` is revision-controlled in the same way as `%txt`, so its `+grad` is simply `++ grad %txt`. Of course, `+txt` must be defined in `+grow` and `+grab` as well.
46+
47+We mentioned that `+noun` is the only mandatory arm in `+grab`, but there are a couple of others that, while not mandatory, are of particular interest.
48+
49+The first is a `+mime` arm for converting to and from the `%mime` `mark`. When you `|commit` a file to a `desk` mounted to Unix, Clay will receive the data as a `%mime` `mark`, and then convert it to the `mark` matching the file extension. It will perform the same operation in reverse when mounting a `desk` to Unix. For this reason, any `mark` you wish to be able to access from the Unix filesystem should have `%mime` conversion routines. In certain cases (such as the scry interface), Eyre will also need to convert your `mark` to a `%mime` in order to encode it in an HTTP response, so you may require a `+mime` arm for that reason as well.
50+
51+The second case of interest is the `+json` arm for converting to and from a `%json` `mark`. If, for example, you want to write a Gall agent to which you can subscribe through Eyre's channel system, it must produce data with a `mark` containing `%json` conversion routines. If it doesn't, Eyre will not be able to deliver the data to the subscribed HTTP client in the SSE stream.
52+
53+## Sections
54+
55+[Writing Marks](/docs/arvo/clay/marks/writing-marks) - A practical walk-through of writing a `mark` file.
56+
57+[Using Marks](/docs/arvo/clay/marks/using-marks) - Details of using `mark` conversion gates and `mark` cores in your own code.
58+
59+[Examples](/docs/arvo/clay/marks/examples) - The example code used in the Writing Marks guide.
content/docs/arvo/clay/marks/using-marks.mdnew file+240
@@ -0,0 +1,240 @@
1++++
2+title = "Using Marks"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+In the last document, [Writing Marks](/docs/arvo/clay/marks/writing-marks), we walked through writing `mark` files and touched on how Clay handles them. They needn't just be left to background vane processes though, you can also use them yourself in your code.
8+
9+There are two kinds of cores that Clay can build for you: A `mark` conversion gate and a `mark` core. Each has two kinds: Statically typed and dynamically typed. Clay has a `care` for producing each of these:
10+
11+- `%b` - Build a dynamically typed `mark` core.
12+- `%c` - Build a dynamically typed `mark` conversion gate.
13+- `%e` - Build a statically typed `mark` core.
14+- `%f` - Build a statically typed `mark` conversion gate.
15+
16+You can either use these by `%pass`ing Clay a [%warp task](/docs/arvo/clay/tasks#warp) with the appropriate `care`, or else with a [Clay scry](/docs/arvo/clay/scry). In the examples here we've used the latter.
17+
18+## mark conversion gates
19+
20+`mark` conversion gates simply convert from one `mark` to another.
21+
22+### Static
23+
24+A static `mark` conversion gate looks like `$-(a b)`, where `a` is the type of the `mark` you're converting _from_, and `b` is type of the `mark` you're converting _to_. For example, a `mark` conversion gate from `%txt` to `%mime` would look like `$-(wain mime)`. You'd simply feed it a `wain` and get a `$mime` in return.
25+
26+#### Example
27+
28+We get our `%txt` to `%mime` `mark` conversion gate with a `%f` scry like so:
29+
30+```
31+> =txt-to-mime .^($-(wain mime) %cf /===/txt/mime)
32+```
33+
34+Note we had to specify the type of the gate as `$-(wain mime)` in the scry - if the type returned by the scry doesn't match that specification it'll fail. This is where a statically typed `mark` conversion gate differs from the dynamically typed gate, which we'll discuss later.
35+
36+Now that we have our conversion gate, we can just call it with a valid `wain` and we'll get our `$mime` in return:
37+
38+```
39+> (txt-to-mime ~['foo'])
40+[p=/text/plain q=[p=3 q=7.303.014]]
41+```
42+
43+### Dynamic
44+
45+A dynamically typed `mark` conversion gate is called a `$tube:clay`, and looks like:
46+
47+```hoon
48++$ tube $-(vase vase)
49+```
50+
51+As you can see from the type definition, it takes and returns a `vase` rather than needing the types explicitly defined. Rather than failing on a type mismatch when the scry is performed, it'll instead fail when it's actually run and fed a `vase` of the wrong type. Apart from handling `vase`s, it otherwise behaves the same as a statically typed `mark` conversion gate.
52+
53+#### Example
54+
55+We get our `%txt` to `%mime` `$tube` with a `%c` scry like so:
56+
57+```
58+> =txt-mime-tube .^(tube:clay %cc /===/txt/mime)
59+```
60+
61+And then we can again feed it the `wain` that a `%txt` `mark` wants, only this time it's wrapped in a `vase`:
62+
63+```
64+> !< mime (txt-mime-tube !>(~['foo']))
65+[p=/text/plain q=[p=3 q=7.303.014]]
66+```
67+
68+We then get our `$mime` back, but also in a `vase`.
69+
70+## mark cores
71+
72+While a `mark` conversion gate is built from functions defined in `+grab` and `+grow`, a `mark` core gives you everything in `+grad` so you can create diffs, merge diffs, patch files, etc. An extra arm `+vale` is also included that lets you convert a `noun` to the type the `%mark` takes by running the `+noun` arm of `+grab` in the original `mark` file.
73+
74+### Static
75+
76+A statically typed `mark` core is a `(nave:clay a b)` where `a` is the type of the `mark` and `b` is the type for diffs (which is the type of the `mark` specified in `+form:grad`). For example, a static `mark` core for a `%txt` `mark` looks like `(nave:clay wain (urge:clay cord))`.
77+
78+`+nave:clay` looks like this in full:
79+
80+```hoon
81+++ nave
82+ |$ [typ dif]
83+ $_
84+ ^?
85+ |%
86+ ++ diff |~([old=typ new=typ] *dif)
87+ ++ form *mark
88+ ++ join |~([a=dif b=dif] *(unit (unit dif)))
89+ ++ mash
90+ |~ [a=[ship desk dif] b=[ship desk dif]]
91+ *(unit dif)
92+ ++ pact |~([typ dif] *typ)
93+ ++ vale |~(noun *typ)
94+ --
95+```
96+
97+In brief, the arms of the core do the following:
98+
99+- `+form` - `mark` for diffs.
100+- `+vale` - Clam `noun` to the `mark`'s type.
101+- `+diff` - Create diff of two files.
102+- `+pact` - Patch a file with a diff.
103+- `+join` - Merge two diffs, returning `~` if there's a conflict.
104+- `+mash` - Force merge of two diffs.
105+
106+#### Examples
107+
108+First we get the `%txt` `mark` core with a `%e` scry:
109+
110+```
111+> =txt-nave .^((nave:clay wain (urge:clay cord)) %ce /===/txt)
112+```
113+
114+Note we specified the `mark` type `wain` and diff type `(urge:clay cord)` in the `nave` returned by the scry.
115+
116+We can see the `mark` for diffs with `+form`:
117+
118+```
119+> form.txt-nave
120+%txt-diff
121+```
122+
123+To clam a noun to the type of the `mark` (a `wain` in the case of a `%txt` `mark`), we can call `+vale` with a `noun`:
124+
125+```
126+> (vale:txt-nave ~['foo' 'bar'])
127+<|foo bar|>
128+```
129+
130+We can create a diff of two files with `+diff`:
131+
132+```
133+> (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'zoo' 'baz'])
134+~[[%.y p=1] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]
135+```
136+
137+Let's create some more diffs for experimentation:
138+
139+```
140+> =diff-a (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'zoo' 'baz'])
141+> =diff-b (diff:txt-nave ~['foo' 'bar' 'baz'] ~['zap' 'bar' 'baz'])
142+> =diff-c (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'bla' 'baz'])
143+```
144+
145+If we try merging diffs `a` and `b` with `+join`, we get a new merged diff back in a `unit`:
146+
147+```
148+> (join:txt-nave diff-a diff-b)
149+[~ [~ ~[[%.n p=<|foo|> q=<|zap|>] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]]]
150+```
151+
152+If we try merging diffs `a` and `c` however, we get `~` because of a conflict:
153+
154+```
155+> (join:txt-nave diff-a diff-c)
156+[~ ~]
157+```
158+
159+If we run `+mash` on `a` and `b` we get the same diff as with `+join` (sans the `unit`):
160+
161+```
162+> (mash:txt-nave [our %home diff-a] [our %blah diff-b])
163+[~ ~[[%.n p=<|foo|> q=<|zap|>] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]]
164+```
165+
166+If we `+mash` `a` and `c`, however, we get a diff with the conflict annotated rather than just `~`:
167+
168+```
169+> (mash:txt-nave [our %home diff-a] [our %blah diff-c])
170+[ ~
171+ ~[
172+ [%.y p=1]
173+ [ %.n
174+ p=<|bar|>
175+ q
176+ <|>>>>>>>>>>>> ~zod/home zoo ++++++++++++ bar ------------ bla <<<<<<<<<<<< ~zod/blah|>
177+ ]
178+ [%.y p=1]
179+ ]
180+]
181+```
182+
183+Note that the `%txt` `mark` annotates conflicts, but there are no specific rules around how the `+mash` arm should force-merge conflicting diffs apart from that it must return a valid diff, however the `mark` specified in `+form` defines that.
184+
185+Finally, we can patch our `wain` with diff `a` and get a new, modified `wain`:
186+
187+```
188+> (pact:txt-nave ~['foo' 'bar' 'baz'] diff-a)
189+<|foo zoo baz|>
190+```
191+
192+### Dynamic
193+
194+A dynamically typed `mark` core is a `$dais:clay`, which looks like:
195+
196+```hoon
197++$ dais
198+ $_ ^|
199+ |_ sam=vase
200+ ++ diff |~(new=_sam *vase)
201+ ++ form *mark
202+ ++ join |~([a=vase b=vase] *(unit (unit vase)))
203+ ++ mash
204+ |~ [a=[ship desk diff=vase] b=[ship desk diff=vase]]
205+ *(unit vase)
206+ ++ pact |~(diff=vase sam)
207+ ++ vale |~(noun sam)
208+ --
209+```
210+
211+It has the same arms as the statically typed `mark` core, the difference is that it takes and returns `vase`s rather than the data directly. Additionally, it's a door rather than an ordinary core, and takes the type of the `mark` wrapped in a `vase` as its argument.
212+
213+#### Examples
214+
215+We can get a `%txt` `mark` `dais` with a `%b` scry:
216+
217+```
218+> =txt-dais .^(dais:clay %cb /===/txt)
219+```
220+
221+Its `+form` arm functions the same as a static core:
222+
223+```
224+> form.txt-dais
225+%txt-diff
226+```
227+
228+So does `+vale` except it returns a `vase`:
229+
230+```
231+> !< wain (vale:txt-dais ~['foo' 'bar'])
232+<|foo bar|>
233+```
234+
235+All the other arms also deal in `vase`s. Because it's a door, the `+pact` and `+diff` arms take the original file in a `vase` as the door sample rather than being given directly to the arm. Calling `+diff` arm, for example, works like so:
236+
237+```
238+> !< (urge:clay cord) (~(diff txt-dais !>(~['foo' 'bar'])) !>(~['foo' 'baz']))
239+~[[%.y p=1] [%.n p=<|bar|> q=<|baz|>]]
240+```
content/docs/arvo/clay/marks/writing-marks.mdnew file+333
@@ -0,0 +1,333 @@
1++++
2+title = "Writing Marks"
3+weight = 2
4+template = "doc.html"
5++++
6+
7+Here we'll walk through a practical example of writing a `mark` file.
8+
9+We'll create a `mark` for CSV (comma separated values) files, a simple format for storing tabular data in a text file. Note that there's already a `csv.hoon` `mark` and library, but we'll create new ones for demonstrative purposes. It shouldn't be an issue to overwrite the existing ones on a fakezod.
10+
11+CSV files separate fields with commas and rows with line breaks. They look something like:
12+
13+```
14+foo,bar,baz
15+blah,blah,blah
16+1,2,3
17+```
18+
19+There is a little complexity surrounding special characters in fields and line endings, but otherwise the only other rule is that all rows must have the same number of fields. You can refer to [RFC4180 on the IETF website](https://datatracker.ietf.org/doc/html/rfc4180) for more details.
20+
21+We'll represent such a structure in Hoon as a `(list (list @t))` like:
22+
23+```hoon
24+[['foo' 'bar' 'baz' ~] ['blah' 'blah' 'blah' ~] ['1' '2' '3' ~] ~]
25+```
26+
27+We could perhaps create the type with a `$|` rune to include row-length validation in the mold itself, but a `(list (list @t))` is simpler for demonstrative purposes.
28+
29+## A simple mark
30+
31+Let's begin with the simplest `mark` file:
32+
33+```hoon
34+|_ csv=(list (list @t))
35+++ grab
36+ |%
37+ ++ noun (list (list @t))
38+ --
39+++ grow
40+ |%
41+ ++ noun csv
42+ --
43+++ grad %noun
44+--
45+```
46+
47+The door takes a `(list (list @t))` as its sample, and we've given it a face of `csv` so we can easily reference it. Note its face could be anything, it needn't be the name of our `mark`. When we're doing something with data that has a `%csv` `mark` like converting it to another `mark` or creating a diff, this is where our data will reside.
48+
49+Next we have the `+grab` arm of our door, which contains a core with arms for converting _to_ our `mark` _from_ other `mark`s. We've given it one arm for the `%noun` `mark` - the most generic `mark` which will take any `noun`. Our `+noun` arm will simply clam whatever it's given with the `(list (list @t))` `mold`.
50+
51+Next is the `+grow` arm which does the inverse of `+grab`, converting _from_ our `mark` _to_ another `mark`. We've also given it a `+noun` arm, this time it will simply return the door's sample named `csv`, which is of course already a `noun`.
52+
53+Note that the `+noun` arm is _mandatory_ in `+grab`. Clay cannot build a `mark` core without it. Conversion arms for any other `mark`s apart from `%noun` are optional.
54+
55+Finally we have the `+grad` arm. This arm specifies functions for revision control like creating diffs, patching files and so on. In our case, rather than writing all those functions, we've just delegated those tasks to the `%noun` `mark`. We can do this because we've specified conversion routines to and from the `%noun` `mark` in our `+grow` and `+grab` arms. When we modify a file with a `%csv` `mark`, Clay will convert our data to a `%noun` `mark`, execute the necessary `+grad` functions from the `%noun` `mark` file, and then convert it back to a `%csv` `mark` again.
56+
57+So now we have a valid `%csv` `mark` file. If we save this as `csv.hoon` in the `/mar` directory we could store `%csv` data in Clay. This may be sufficient for some applications, but what if we want to import a CSV file from Unix or elsewhere? In the next section, we'll look at conversions to and from a `%mime` `mark` to address this.
58+
59+## `%mime` conversions
60+
61+The `$mime` type represents raw data from Unix or elsewhere. For example, if a text file from Unix containing the word `foo` were converted to a `$mime` type in Urbit, it would look something like:
62+
63+```hoon
64+[/text/plain q=[p=3 q=7.303.014]]
65+```
66+
67+`/text/plain` is its [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) and `p.q` is the byte-length of `q.q`, which is the data itself as an `atom`.
68+
69+The `%mime` `mark` is used by Clay to store and convert `$mime` data. It's an important `mark` for moving files from Unix to Urbit and vice versa. When you add a file to a `desk` you have mounted to Unix and `|commit` the change, Clay will first receive the file as a `%mime` `mark`, then convert from a `%mime` to whatever `mark` matches the file extension. For example, `foo.txt` will be converted from `%mime` to `%txt`. Additionally, data fetched by Iris over HTTP will come in as a `$mime-data:http`, which is an unvalidated form of `$mime` that you may wish to convert to a `%mime` `mark` and then to another `mark`. Likewise with Eyre, some of the lower-level interfaces receive HTTP requests with `$mime-data:http` in them.
70+
71+So with the nature of the `%mime` `mark` hopefully now clear, the reason we want conversion methods to and from `%mime` in our `%csv` `mark` is so we can import CSV files from Unix and vice versa.
72+
73+Since a CSV file on Unix will just be a long string with ASCII or UTF-8 encoding, we can treat `q.q` in the `$mime` as a `cord`, and thus write a parser to convert it to a `(list (list @t))`. For this purpose, here's a library: `csv.hoon`, which you can view in full on the [Examples](/docs/arvo/clay/marks/examples#libcsvhoon) page.
74+
75+The library contains four functions:
76+
77+- `+de-csv` - Parse a CSV `cord` to a `(list (list @t))`.
78+- `+en-csv` - Encode a `(list (list @t))` as a CSV `cord`.
79+- `+validate` - Check all rows of `(list (list @t))` are the same length.
80+- `+csv-join` - Ignore this for now, we'll use it later on.
81+
82+The decoding and encoding arms use parsing functions from the Hoon standard library. It's not important to be familiar with parsing in Hoon for our purposes here, but you can have a look at the [Parsing Guide](/docs/hoon/guides/parsing) in the Hoon documentation if you're interested. The important thing to note is that `+de-csv` takes a valid CSV-format `@t` and returns a `(list (list @t))`, and `+en-csv` does the reverse - it takes a `(list (list @t))` and returns a CSV-format `@t`.
83+
84+Let's try the library in the dojo. After we've added it to `/lib` and run `|commit`, we can build the file:
85+
86+```
87+> =csv -build-file %/lib/csv/hoon
88+```
89+
90+...try decode a CSV-format `@t`:
91+
92+```
93+> (de-csv:csv 'foo,bar,baz\0ablah,blah,blah\0a1,2,3')
94+~[<|foo bar baz|> <|blah blah blah|> <|1 2 3|>]
95+```
96+
97+...and try encode a `(list (list @t))` as a CSV-format `@t`:
98+
99+```
100+> (en-csv:csv [['foo' 'bar' 'baz' ~] ['blah' 'blah' 'blah' ~] ['1' '2' '3' ~] ~])
101+'foo,bar,baz\0ablah,blah,blah\0a1,2,3\0a'
102+```
103+
104+With that working, we can add an import for our library to our `%csv` `mark` defintion and add a `+mime` arm to both our `+grab` and `+grow` arms:
105+
106+```hoon
107+/+ *csv
108+|_ csv=(list (list @t))
109+++ grab
110+ |%
111+ ++ mime |=((pair mite octs) (de-csv q.q))
112+ ++ noun
113+ |= n=*
114+ ^- (list (list @t))
115+ =/ result ((list (list @t)) n)
116+ ?> (validate result)
117+ result
118+ --
119+++ grow
120+ |%
121+ ++ mime
122+ ?> (validate csv)
123+ [/text/csv (as-octs:mimes:html (en-csv csv))]
124+ ++ noun
125+ ?> (validate csv)
126+ csv
127+ --
128+++ grad %noun
129+--
130+```
131+
132+In `+grab` we've added a `+mime` arm to convert _from_ a `%mime` `mark` _to_ our `%csv` `mark`. It's a simple gate that takes a `$mime` (specified as `(pair mite octs)` to avoid conflict with the arm name), runs the data through the `+de-csv` function and returns a `(list (list @t))` of the CSV data.
133+
134+We've also added a `+mime` arm to `+grow` for converting _from_ our `%csv` `mark` _to_ a `%mime` `mark`. We encode our `(list (list @t))` `csv` sample with our `+en-csv` function and then run that through `as-octs:mimes:html` to get a `$octs` (so it has the byte-length). We also add the `/text/csv` MIME type so it's a valid `$mime`.
135+
136+Additionally, we've used the `+validate` function in a few places to make sure our CSV data has consistent row lengths.
137+
138+If we save the above mark file as `csv.hoon` in `/mar` and `|commit %home`, we should now be able to import CSV files into Urbit. Let's give it a go. In the root of our `%home` `desk`, let's add a file named `foo.csv` with the following contents:
139+
140+```
141+foo,bar,baz
142+blah,blah,blah
143+1,2,3
144+```
145+
146+If we now `|commit %home`, we should see it's been successfully added:
147+
148+```
149+> |commit %home
150+>=
151++ /~zod/home/4/foo/csv
152+```
153+
154+And if we try reading the file with the `-read` thread:
155+
156+```
157+> -read [%x our %home da+now /foo/csv]
158+~[<|foo bar baz|> <|blah blah blah|> <|1 2 3|>]
159+```
160+
161+We can see our `%csv` `mark` has successfully converted our `foo.csv` file to a `(list (list @t))` when it was imported.
162+
163+Let's try the other direction now. We can create a new `bar.csv` files in the root of `%home` from the dojo like so:
164+
165+```
166+> */bar/csv ~[['abc' 'def' ~] ['ghi' 'jkl' ~]]
167++ /~zod/home/5/bar/csv
168+```
169+
170+And if we check it in the terminal on the Unix side we can see it's been correctly encoded:
171+
172+```
173+> cat zod/home/bar.csv
174+abc,def
175+ghi,jkl
176+```
177+
178+So now our `%csv` `mark` lets us move data in and out of Urbit. In the next section, we'll look at the `+grad` arm in more detail.
179+
180+## `+grad`
181+
182+So far we've just delegated `+grad` functions to the `%noun` `mark`, but now we'll look at writing our own.
183+
184+For demonstrative purposes, we can just poach the algorithms used in the `+grad` arm of the `%txt` `mark` and modify them to take our `(list (list @t))` type instead of a `wain`. It's not the most efficient algorithm for a CSV file but it'll do the job.
185+
186+Our diff format will be a `(urge:clay (list @t))`, and we'll use some `differ` functions from `zuse.hoon` like `+loss`, `+lusk` and `+lurk` to produce diffs and apply patches.
187+
188+The [csv.hoon library](/docs/arvo/clay/marks/examples#libcsvhoon) we imported also contains a `+csv-join` function which we'll use in the `+join` arm, just to save space here.
189+
190+Here's the new `%csv` `mark` defintion:
191+
192+```hoon
193+/+ *csv
194+|_ csv=(list (list @t))
195+++ grab
196+ |%
197+ ++ mime |=((pair mite octs) (de-csv q.q))
198+ ++ noun
199+ |= n=*
200+ ^- (list (list @t))
201+ =/ result ((list (list @t)) n)
202+ ?> (validate result)
203+ result
204+ --
205+++ grow
206+ |%
207+ ++ mime
208+ ?> (validate csv)
209+ [/text/csv (as-octs:mimes:html (en-csv csv))]
210+ ++ noun
211+ ?> (validate csv)
212+ csv
213+ --
214+++ grad
215+ |%
216+ ++ form %csv-diff
217+ ++ diff
218+ |= bob=(list (list @t))
219+ ^- (urge:clay (list @t))
220+ ?> (validate csv)
221+ ?> (validate bob)
222+ (lusk:differ csv bob (loss:differ csv bob))
223+ ++ pact
224+ |= dif=(urge:clay (list @t))
225+ ^- (list (list @t))
226+ =/ result (lurk:differ csv dif)
227+ ?> (validate result)
228+ result
229+ ++ join
230+ |= $: ali=(urge:clay (list @t))
231+ bob=(urge:clay (list @t))
232+ ==
233+ ^- (unit (urge:clay (list @t)))
234+ (csv-join ali bob)
235+ ++ mash
236+ |= $: [ship desk (urge:clay (list @t))]
237+ [ship desk (urge:clay (list @t))]
238+ ==
239+ ^- (urge:clay (list @t))
240+ ~|(%csv-mash !!)
241+ --
242+--
243+```
244+
245+In our modified `+grad` arm, we've replaced the `%noun` delegation with a core containing five arms: `+form`, `+diff`, `+pact`, `+join`, and `+mash`. These arms are all required for a valid `+grad` if it's not delegated to another `mark`. We'll now look at each in detail.
246+
247+### `+form`
248+
249+```hoon
250+++ form %csv-diff
251+```
252+
253+`+form` simply specifies the `mark` of the diff file that may be produced by other `+grad` functions. If your diff is the same type as your `mark`, it could just specify itself like `%csv`. In our case our diff is a `(urge:clay (list @t))` rather than a `(list (list @t))`, so we need a separate mark file for the diff itself.
254+
255+Here's another `mark` file which can be saved as `csv-diff.hoon` in `/mar`:
256+
257+```hoon
258+|_ dif=(urge:clay (list @t))
259+++ grab
260+ |%
261+ ++ noun (urge:clay (list @t))
262+ --
263+++ grow
264+ |%
265+ ++ noun dif
266+ --
267+++ grad %noun
268+--
269+```
270+
271+It's very bare-bones, we just need it for our `%csv` `mark` to work. In our `%csv` `mark`, we've specified it as `%csv-diff` in `+form`.
272+
273+### `+diff`
274+
275+```hoon
276+++ diff
277+ |= bob=(list (list @t))
278+ ^- (urge:clay (list @t))
279+ ?> (validate csv)
280+ ?> (validate bob)
281+ (lusk:differ csv bob (loss:differ csv bob))
282+```
283+
284+This arm produces the diff of two `%csv` files. The first `%csv` file will be given as the sample of the parent door, which if you'll recall we gave a face of `csv`. The second `%csv` file will be given as the sample of the gate in `+diff`, which we've named `bob` here. We then just produce the diff of these two files and return it as the type of the mark specified in `+form`, which in our case is `(urge:clay (list @t))` for a `%csv-diff`. Clay will use `+diff` when a file is revised, so it doesn't have to store a whole new copy of the file each time it's modified.
285+
286+### `+pact`
287+
288+```hoon
289+++ pact
290+ |= dif=(urge:clay (list @t))
291+ ^- (list (list @t))
292+ =/ result (lurk:differ csv dif)
293+ ?> (validate result)
294+ result
295+```
296+
297+`+pact` patches a `%csv` file with the given diff. Its gate takes a diff and applies it to the `%csv` given as the sample of the parent door (which we gave a face of `csv`). If the patch succeeds, it will return a new `%csv` file - a valid `(list (list @t))`. When we read a file that's been modified in Clay, Clay will apply all the diffs it has with `+pact` and return the resulting file.
298+
299+### `+join`
300+
301+```hoon
302+++ join
303+ |= $: ali=(urge:clay (list @t))
304+ bob=(urge:clay (list @t))
305+ ==
306+ ^- (unit (urge:clay (list @t)))
307+ (csv-join ali bob)
308+```
309+
310+The `+join` arm merges two different diffs. It takes them both as the sample of its gate (which we've named `ali` and `bob`), and returns a new diff wrapped in a `unit` like `(unit (urge:clay (list @t)))`. The `unit` will be `~` if the merge failed due to a conflict. This is used by Clay in some cases when `desk`s are merged. If diff merges are not possible for your use case, you could just have it always return `~`.
311+
312+### `+mash`
313+
314+```hoon
315+++ mash
316+ |= $: [ship desk (urge:clay (list @t))]
317+ [ship desk (urge:clay (list @t))]
318+ ==
319+ ^- (urge:clay (list @t))
320+ ~|(%csv-mash !!)
321+```
322+
323+This is like `+join` except it forces a diff merge even if there's a conflict. Rather than returning a `unit`, it just returns the diff - a `(urge:clay (list @t))` in our case. Also unlike `+join`, it takes the `ship` and `desk` each diff came from as well as the diff itself.
324+
325+The `+mash` arm is not used by Clay in its file revision operations, so it's safe to just make it a dummy arm that crashes as we've done here. If you were to use it, it would likely just be used manually in an agent, thread or generator.
326+
327+An example of its use would be the `%txt` `mark`, which includes a proper `+mash` function that produces a diff with any conflicts annotated, though how you have `+mash` handle conficts would depend on your use case. If there were no conflicts between the two diffs, it should produce the same diff as the `+join` arm.
328+
329+## Conclusion
330+
331+So there you have it, a fully functional `mark` for CSV files. A `mark` file can be as complex or as simple as you'd like, they're very flexible depending on your use case. Additional conversion methods can always be added as they're needed. For example, with just a few lines of code we could add arms for converting CSV files to `%json` or `%txt` and vice versa.
332+
333+In the next document, we'll look at building and using `mark` cores and `mark` conversion gates in our own code.
content/docs/hoon/reference/_index.md+6−3
@@ -36,15 +36,18 @@ The full story on Hoon's type system.
3636
3737A list of aura types for atoms.
3838
39−### [Runes](/docs/hoon/reference/rune/)
39+## [Runes](/docs/hoon/reference/rune/)
4040
4141Syntax and semantics for Hoon's rune system.
4242
43−### [Limbs and Wings](/docs/hoon/reference/limbs/)
43+## [Limbs and Wings](/docs/hoon/reference/limbs/)
4444
4545How to find data inside Hoon subjects.
4646
47−### [Standard Library](/docs/hoon/reference/stdlib/)
47+## [Standard Library](/docs/hoon/reference/stdlib/)
4848
4949Reference material for the Hoon standard library.
5050
51+## [Zuse](/docs/hoon/reference/zuse/)
52+
53+Reference material for the Zuse library.
content/docs/hoon/reference/rune/ket.md+12−3
@@ -63,9 +63,18 @@ Regular: **1-fixed**.
6363
6464##### Discussion
6565
66−A mold is an idempotent gate that is guaranteed to produce a noun of that type. If an input value isn't of the correct type, the bunt value of that type is returned. (See `^*`.)
67−
68−`^:` is used to produce a gate that is much like a mold, except that instead of producing a bunt value when the input value is of the wrong type, it crashes.
66+A mold is an idempotent gate that is guaranteed to produce a noun of that type.
67+If an input value isn't of the correct type, the bunt value of that type is
68+returned. (See `^*`.)
69+
70+`^:` is used to produce a gate that is much like a mold, except that instead of
71+producing a bunt value when the input value is of the wrong type, it crashes.
72+
73+One may expect that `^:(path /foo)` would result in a syntax error since `^:`
74+only takes one child, but instead it will parse as `=< ^ %:(path /foo)`. Since
75+`:` is the irregular syntax for `=<` this is is parsed as "get `^` (i.e. the
76+mold for cells) from a subject of `(path /foo)`", with `:` being the irregular
77+syntax for `=<`.
6978
7079##### Examples
7180
content/docs/hoon/reference/stdlib/2b.md+37
@@ -785,6 +785,19 @@ We can fix this with `|:`:
78578524
786786```
787787
788+If you check the definition of `+mul`, you'll see that it also utilizes this
789+pattern.
790+
791+We can check explicitly what sequence of operations `+reel` performs like this:
792+```
793+> =f |: [l='e_l' r='e_r']
794+ ^- @t
795+ :((cury cat 3) '(' l '*' r ')')
796+> (reel "abcde" f)
797+'(a*(b*(c*(d*(e*e_r)))))'
798+```
799+
800+
788801---
789802
790803## `++roll`
@@ -863,6 +876,30 @@ We can fix this with `|:`:
863876> (roll `(list @)`~[1 2 3 4] |:([a=1 b=1] (mul a b)))
86487724
865878```
879+If you check the definition of `+mul`, you'll see that it also utilizes this
880+pattern.
881+
882+We can check explicitly what sequence of operations `+roll` performs like this:
883+```
884+> =f |: [l='e_l' r='e_r']
885+ ^- @t
886+ :((cury cat 3) '(' l '*' r ')')
887+> (roll "abcde" f)
888+'(e*(d*(c*(b*(a*e_r)))))
889+```
890+This is in contrast to what one might expect:
891+```
892+> =foldl
893+ |* [l=(list) f=$-([* *] *)]
894+ ^- f
895+ ?~ l +<-.f
896+ %= $
897+ +<-.f (f +<-.f i.l)
898+ l t.l
899+ ==
900+> (foldl "abcde" f)
901+'(((((e_l*a)*b)*c)*d)*e)'
902+```
866903
867904---
868905
content/docs/hoon/reference/zuse/2d_1-5.mdnew file+587
@@ -0,0 +1,587 @@
1++++
2+title = "2d(1-5): To JSON, Wains"
3+weight = 40
4+template = "doc.html"
5++++
6+
7+## `++to-wain:format`
8+
9+Cord to line list
10+
11+Convert `txt` to a wain, breaking on newline characters.
12+
13+#### Accepts
14+
15+`txt` is a `@t`.
16+
17+#### Produces
18+
19+A `wain`, which is a `(list @t)`.
20+
21+#### Source
22+
23+```hoon
24+++ to-wain
25+ |= txt=cord
26+ ^- wain
27+ =/ len=@ (met 3 txt)
28+ =/ cut =+(cut -(a 3, c 1, d txt))
29+ =/ sub sub
30+ =| [i=@ out=wain]
31+ |- ^+ out
32+ =+ |- ^- j=@
33+ ?: ?| =(i len)
34+ =(10 (cut(b i)))
35+ ==
36+ i
37+ $(i +(i))
38+ =. out :_ out
39+ (cut(b i, c (sub j i)))
40+ ?: =(j len)
41+ (flop out)
42+ $(i +(j))
43+```
44+
45+#### Examples
46+
47+```
48+> (to-wain:format 'foo\0abar\0abaz')
49+<|foo bar baz|>
50+```
51+
52+---
53+
54+## `++of-wain:format`
55+
56+Line list to cord
57+
58+Convert `tez` to a cord, separating each line with a newline character.
59+
60+#### Accepts
61+
62+`tez` is a `wain`, which is a `(list @t)`.
63+
64+#### Produces
65+
66+A `@t`.
67+
68+#### Source
69+
70+```hoon
71+++ of-wain
72+ |= tez=wain ^- cord
73+ (rap 3 (join '\0a' tez))
74+```
75+
76+#### Examples
77+
78+```
79+> (of-wain:format ~['foo' 'bar' 'baz'])
80+'foo\0abar\0abaz'
81+```
82+
83+---
84+
85+## `++of-wall:format`
86+
87+Line list to tape
88+
89+Convert `a` to a tape, separating each line with a newline character.
90+
91+#### Accepts
92+
93+`a` is a `wall`, which is a `(list tape)`
94+
95+#### Produces
96+
97+A `tape`.
98+
99+#### Source
100+
101+```hoon
102+++ of-wall
103+ |= a=wall ^- tape
104+ ?~(a ~ "{i.a}\0a{$(a t.a)}")
105+```
106+
107+#### Examples
108+
109+```
110+> (of-wall:format ~["foo" "bar" "baz"])
111+"foo\0abar\0abaz\0a"
112+```
113+
114+---
115+
116+## `++json-rn:format`
117+
118+json to rn parser
119+
120+This function is used internally by [+ne](/docs/hoon/reference/zuse/2d_6#nedejsformat) and would not typically be used directly. It is a `rule` that parses a real number string to a `rn` in a unit.
121+
122+#### Accepts
123+
124+A `nail` containing a real number.
125+
126+#### Produces
127+
128+An `edge` containing a `(unit rn)`.
129+
130+#### Source
131+
132+```hoon
133+++ json-rn
134+ %+ knee *rn |.
135+ ;~ plug
136+ (easy %d)
137+ ;~(pose (cold | hep) (easy &))
138+ ;~ plug dim:ag
139+ ;~ pose
140+ ;~ pfix dot
141+ %+ sear
142+ |= a=tape
143+ =/ b (rust a dum:ag)
144+ ?~ b ~
145+ (some [(lent a) u.b])
146+ (plus (shim '0' '9'))
147+ ==
148+ (easy [0 0])
149+ ==
150+ ;~ pose
151+ ;~ pfix
152+ (mask "eE")
153+ ;~ plug
154+ ;~(pose (cold | hep) (cold & lus) (easy &))
155+ ;~ pose
156+ ;~(pfix (plus (just '0')) dim:ag)
157+ dim:ag
158+ ==
159+ ==
160+ ==
161+ (easy [& 0])
162+ ==
163+ ==
164+ ==
165+```
166+
167+#### Examples
168+
169+```
170+> (rush '2.47' json-rn:format)
171+[~ [%d a=%.y b=[c=2 [d=2 e=47] f=%.y i=0]]]
172+```
173+
174+```
175+> (rush '123' json-rn:format)
176+[~ [%d a=%.y b=[c=123 [d=0 e=0] f=%.y i=0]]]
177+```
178+
179+```
180+> (rush 'a' json-rn:format)
181+~
182+```
183+
184+---
185+
186+## `++enjs:format`
187+
188+Container arm for JSON encoders
189+
190+The `core` inside this arm contains a collection of functions for converting various types of data to `json`. The `json` type is defined in `lull.hoon` as:
191+
192+```hoon
193++$ json :: normal json value
194+ $@ ~ :: null
195+ $% [%a p=(list json)] :: array
196+ [%b p=?] :: boolean
197+ [%o p=(map @t json)] :: object
198+ [%n p=@ta] :: number
199+ [%s p=@t] :: string
200+ == ::
201+```
202+
203+This container arm doesn't do anything itself. The different `json` encoding functions are documented individually below.
204+
205+---
206+
207+### `++frond:enjs:format`
208+
209+Object from key-value pair
210+
211+Produces a `json` object containing `q` with a key of `p`.
212+
213+#### Accepts
214+
215+`p` is a `@t` key.
216+
217+`q` is any `json`.
218+
219+#### Produces
220+
221+A `json` object.
222+
223+#### Source
224+
225+```hoon
226+++ frond
227+ |= [p=@t q=json]
228+ ^- json
229+ [%o [[p q] ~ ~]]
230+```
231+
232+#### Examples
233+
234+```
235+> (frond:enjs:format 'foo' s+'bar')
236+[%o p={[p='foo' q=[%s p='bar']]}]
237+```
238+
239+```
240+> (crip (en-json:html (frond:enjs:format 'foo' s+'bar')))
241+'{"foo":"bar"}'
242+```
243+
244+---
245+
246+### `++pairs:enjs:format`
247+
248+Object from key-value pair list
249+
250+Produces a `json` object containing each key-value pair in list `a`.
251+
252+#### Accepts
253+
254+`a` is a `(list [@t json])`.
255+
256+#### Produces
257+
258+A `json` object.
259+
260+#### Source
261+
262+```hoon
263+++ pairs
264+ |= a=(list [p=@t q=json])
265+ ^- json
266+ [%o (~(gas by *(map @t json)) a)]
267+```
268+
269+#### Examples
270+
271+```
272+> =a ~[['foo' n+~.123] ['bar' s+'abc'] ['baz' b+&]]
273+> (pairs:enjs:format a)
274+[%o p={[p='bar' q=[%s p='abc']] [p='baz' q=[%b p=%.y]] [p='foo' q=[%n p=~.123]]}]
275+> (crip (en-json:html (pairs:enjs:format a)))
276+'{"foo":123,"baz":true,"bar":"abc"}'
277+```
278+
279+---
280+
281+### `++tape:enjs:format`
282+
283+String from tape
284+
285+Converts `a` into a `json` string.
286+
287+#### Accepts
288+
289+`a` is a `tape`.
290+
291+#### Produces
292+
293+A `json` string.
294+
295+#### Source
296+
297+```hoon
298+++ tape
299+ |= a=^tape
300+ ^- json
301+ [%s (crip a)]
302+```
303+
304+#### Examples
305+
306+```
307+> (tape:enjs:format "foo")
308+[%s p='foo']
309+```
310+
311+```
312+> (crip (en-json:html (tape:enjs:format "foo")))
313+'"foo"'
314+```
315+
316+---
317+
318+### `++wall:enjs:format`
319+
320+String from wall
321+
322+Converts `a` to a `json` string, separating lines with newline characters.
323+
324+#### Accepts
325+
326+`a` is a `wall`, which is a `(list tape)`.
327+
328+#### Produces
329+
330+A `json` string.
331+
332+#### Source
333+
334+```hoon
335+++ wall
336+ |= a=^wall
337+ ^- json
338+ (tape (of-wall a))
339+```
340+
341+#### Examples
342+
343+```
344+> (wall:enjs:format ~["foo" "bar" "baz"])
345+[%s p='foo\0abar\0abaz\0a']
346+```
347+
348+```
349+> (crip (en-json:html (wall:enjs:format ~["foo" "bar" "baz"])))
350+'"foo\\nbar\\nbaz\\n"'
351+```
352+
353+---
354+
355+### `++ship:enjs:format`
356+
357+~~String~~\* from ship
358+
359+Convert ship `a` to a `json` ~~string~~\*.
360+
361+**Note:** Currently this produces a `json` _number_ rather than string, but with the ship name rendered as text rather than a number. This is for Landscape performance reasons and may be reverted at some point.
362+
363+#### Accepts
364+
365+`a` is a `@p`.
366+
367+#### Produces
368+
369+A `json` ~~string~~ number but with the `@p` rendered as text rather than a number.
370+
371+#### Source
372+
373+```hoon
374+++ ship
375+ |= a=^ship
376+ ^- json
377+ [%n (rap 3 '"' (rsh [3 1] (scot %p a)) '"' ~)]
378+```
379+
380+#### Examples
381+
382+```
383+> (ship:enjs:format our)
384+[%n p=~."zod"]
385+```
386+
387+```
388+> (crip (en-json:html (ship:enjs:format our)))
389+'"zod"'
390+```
391+
392+---
393+
394+### `++numb:enjs:format`
395+
396+Number from unsigned
397+
398+Convert `a` to a `json` number.
399+
400+#### Accepts
401+
402+`a` is a `@u`
403+
404+#### Produces
405+
406+A `json` number.
407+
408+#### Source
409+
410+```hoon
411+++ numb
412+ |= a=@u
413+ ^- json
414+ :- %n
415+ ?: =(0 a) '0'
416+ %- crip
417+ %- flop
418+ |- ^- ^tape
419+ ?:(=(0 a) ~ [(add '0' (mod a 10)) $(a (div a 10))])
420+```
421+
422+#### Examples
423+
424+```
425+> (numb:enjs:format 123)
426+[%n p=~.123]
427+```
428+
429+```
430+> (numb:enjs:format 0xffff)
431+[%n p=~.65535]
432+```
433+
434+```
435+> (crip (en-json:html (numb:enjs:format 123)))
436+'123'
437+```
438+
439+---
440+
441+### `++sect:enjs:format`
442+
443+Seconds timestamp
444+
445+Convert time `a` to a Unix seconds timestamp in a `json` number.
446+
447+#### Accepts
448+
449+`a` is a `@da`.
450+
451+#### Produces
452+
453+A `json` number.
454+
455+#### Source
456+
457+```hoon
458+++ sect
459+ |= a=^time
460+ (numb (unt:chrono:userlib a))
461+```
462+
463+#### Examples
464+
465+```
466+> (sect:enjs:format now)
467+[%n p=~.1630407271]
468+```
469+
470+```
471+> (crip (en-json:html (sect:enjs:format now)))
472+'1630407290'
473+```
474+
475+---
476+
477+### `++time:enjs:format`
478+
479+Millisecond timestamp
480+
481+Convert time `a` to a Unix milliseconds timestamp in a `json` number.
482+
483+#### Accepts
484+
485+`a` is a `@da`.
486+
487+#### Produces
488+
489+A `json` number.
490+
491+#### Source
492+
493+```hoon
494+++ time
495+ |= a=^time
496+ (numb (unm:chrono:userlib a))
497+```
498+
499+#### Examples
500+
501+```
502+> (time:enjs:format now)
503+[%n p=~.1630407451204]
504+```
505+
506+```
507+> (crip (en-json:html (time:enjs:format now)))
508+'1630407462905'
509+```
510+
511+---
512+
513+### `++path:enjs:format`
514+
515+String from path
516+
517+Encode path `a` in a `json` string.
518+
519+#### Accepts
520+
521+`a` is a `path`
522+
523+#### Produces
524+
525+A `json` string.
526+
527+#### Source
528+
529+```hoon
530+++ path
531+ |= a=^path
532+ ^- json
533+ [%s (spat a)]
534+```
535+
536+#### Examples
537+
538+```
539+> (path:enjs:format /foo/bar/baz)
540+[%s p='/foo/bar/baz']
541+```
542+
543+```
544+> (crip (en-json:html (path:enjs:format /foo/bar/baz)))
545+'"/foo/bar/baz"'
546+```
547+
548+---
549+
550+### `++tank:enjs:format`
551+
552+Tank as string array
553+
554+Convert tank `a` into a `json` array of strings. The tank is passed through `+wash` with a maximum width of 80 characters specified, so may be split into multiple strings if it's too wide.
555+
556+#### Accepts
557+
558+`a` is a `tank`
559+
560+#### Produces
561+
562+A `json` array of strings.
563+
564+#### Source
565+
566+```hoon
567+++ tank
568+ |= a=^tank
569+ ^- json
570+ [%a (turn (wash [0 80] a) tape)]
571+```
572+
573+#### Examples
574+
575+```
576+> =tan rose+[[" " "[" "]"] ~[leaf+"foo" leaf+"bar" leaf+"baz"]]
577+> (tank:enjs:format tan)
578+[%a p=~[[%s p='[foo bar baz]']]]
579+> (crip (en-json:html (tank:enjs:format tan)))
580+'["[foo bar baz]"]'
581+```
582+
583+```
584+> =tan rose+[[" " "[" "]"] ~[leaf+"aaaaaaaaaaaaaaaaaaaaa" leaf+"bbbbbbbbbbbbbbbbbbb" leaf+"ccccccccccccccccccc" leaf+"dddddddddddddddddd"]]
585+> (crip (en-json:html (tank:enjs:format tan)))
586+'["[ aaaaaaaaaaaaaaaaaaaaa"," bbbbbbbbbbbbbbbbbbb"," ccccccccccccccccccc"," dddddddddddddddddd","]"]'
587+```
content/docs/hoon/reference/zuse/2d_6.mdnew file+1551
@@ -0,0 +1,1551 @@
1++++
2+title = "2d(6): From JSON"
3+weight = 42
4+template = "doc.html"
5++++
6+
7+## `++dejs:format`
8+
9+Container arm for JSON decoding reparsers
10+
11+The `core` inside this arm contains a large collection of functions for converting `json` data to other kinds of nouns. The `json` type is defined in `lull.hoon` as:
12+
13+```hoon
14++$ json :: normal json value
15+ $@ ~ :: null
16+ $% [%a p=(list json)] :: array
17+ [%b p=?] :: boolean
18+ [%o p=(map @t json)] :: object
19+ [%n p=@ta] :: number
20+ [%s p=@t] :: string
21+ == ::
22+```
23+
24+This container arm doesn't do anything by itself. It just contains the core with the rest of the `+dejs` functions which are documented below, plus it defines a couple of things for those functions:
25+
26+```hoon
27+=> |% ++ grub *
28+ ++ fist $-(json grub)
29+ -- ::
30+```
31+
32+A `fist` is a `gate` which takes `json` and produces a `grub`. Apart from a handful of exceptions, all of the functions below are `fist`s. If the functions below aren't adequate for a particular use case, custom `fist`s can easily be written, as long as they conform to the `$-(json grub)` type definition.
33+
34+A `grub` is just defined as `*`, and is the type of the product of a `fist`. In the case of `+dejs`, it can be absolutely any `noun`.
35+
36+Keep in mind that `+grub:dejs:format` and `+fist:dejs:format` defined here (and subsequently referred to as simply `fist` and `grub`) are different to `+grub:dejs-soft:format` and `+fist:dejs-soft:format` for the [+dejs-soft](/docs/hoon/reference/zuse/2d_7) functions, which return `unit`s.
37+
38+---
39+
40+### `++ar:dejs:format`
41+
42+Array as list
43+
44+Convert array `jon` to a list, decoding each item in `jon` with `wit`.
45+
46+The `+ar` function is a wet gate that takes `wit` and produces a new gate which takes `jon`.
47+
48+#### Accepts
49+
50+`wit` is a `fist` and is the sample of the wet gate.
51+
52+`jon` is a `json` array containing the kind of `json` that `wit` handles. `jon` is the sample of the gate produced by the wet gate.
53+
54+#### Produces
55+
56+A `(list [type])` where `[type]` is the type produced by `wit`.
57+
58+#### Source
59+
60+```hoon
61+++ ar
62+ |* wit=fist
63+ |= jon=json ^- (list _(wit *json))
64+ ?> ?=([%a *] jon)
65+ (turn p.jon wit)
66+```
67+
68+#### Examples
69+
70+```
71+> ((ar so):dejs:format a+[s+'foo' s+'bar' s+'baz' ~])
72+<|foo bar baz|>
73+```
74+
75+---
76+
77+### `++as:dejs:format`
78+
79+Array as set
80+
81+Convert array `jon` to a set, decoding each item in `jon` with `a`.
82+
83+The `+as` function is a wet gate that takes `a` and produces a new gate which takes `jon`.
84+
85+#### Accepts
86+
87+`a` is a `fist`, and is the sample of the wet gate.
88+
89+`jon` is a `json` array containing the kind of `json` that `a` takes. `jon` is the sample of the gate produced by the wet gate.
90+
91+#### Produces
92+
93+A `(set [type])` where `[type]` is the type produced by `a`.
94+
95+#### Source
96+
97+```hoon
98+++ as
99+ |* a=fist
100+ (cu ~(gas in *(set _$:a)) (ar a))
101+```
102+
103+#### Examples
104+
105+```
106+> ((as so):dejs:format a+[s+'foo' s+'bar' s+'baz' ~])
107+[n='baz' l={'bar'} r={'foo'}]
108+```
109+
110+---
111+
112+### `++at:dejs:format`
113+
114+Array as tuple
115+
116+Convert array `jon` to a tuple, decoding each item in the array with the corresponding `fist` in list `wil`.
117+
118+The `+at` function is a wet gate that takes `wil` and produces a new gate which takes `jon`.
119+
120+#### Accepts
121+
122+`wil` is a `(pole fist)`, and is the sample of the wet gate. A `pole` is a faceless list.
123+
124+`jon` is a `json` array whose elements are the same kinds of `json` accepted by the `fist`s in `wil` and in the same order. `jon` is the sample of the gate produced by the wet gate.
125+
126+#### Produces
127+
128+A tuple of the same types and in the same order as those produced by the `fist`s in `wil`.
129+
130+#### Source
131+
132+```hoon
133+++ at
134+ |* wil=(pole fist)
135+ |= jon=json
136+ ?> ?=([%a *] jon)
137+ ((at-raw wil) p.jon)
138+```
139+
140+#### Examples
141+
142+```
143+> ((at ~[so ni bo]):dejs:format a+[s+'foo' n+'123' b+& ~])
144+['foo' 123 %.y]
145+```
146+
147+```
148+> ((at ~[so ni bo]):dejs:format a+[b+& s+'foo' n+'123' ~])
149+dojo: hoon expression failed
150+```
151+
152+---
153+
154+### `++at-raw:dejs:format`
155+
156+Array as tuple, raw
157+
158+This function is used internally by `+at` and would not typically be used directly.
159+
160+`+at-raw` converts list `jol` to a tuple, decoding each item in the list with the corresponding function in list `wil`.
161+
162+The `+at-raw` function is a wet gate that takes `wil` and produces a new gate which takes `jol`.
163+
164+#### Accepts
165+
166+`wil` is a `(pole fist)`, and the sample of the wet gate. A `pole` is a faceless list.
167+
168+`jol` is a `(list json)` whose items are the same kinds of `json` accepted by the `fist`s in `wil` and in the same order. `jol` is the sample of the gate produced by the wet gate.
169+
170+#### Produces
171+
172+A tuple of the types and in the same order as those produced by the `fist`s in `wil`.
173+
174+#### Source
175+
176+```hoon
177+++ at-raw
178+ |* wil=(pole fist)
179+ |= jol=(list json)
180+ ?~ jol !!
181+ ?- wil
182+ :: [wit=* t=*]
183+ [* t=*]
184+ => .(wil [wit *]=wil)
185+ ?~ t.wil ?^(t.jol !! (wit.wil i.jol))
186+ [(wit.wil i.jol) ((at-raw t.wil) t.jol)]
187+ ==
188+```
189+
190+#### Examples
191+
192+```
193+> ((at-raw ~[so ni bo]):dejs:format ~[s+'foo' n+'123' b+&])
194+['foo' 123 %.y]
195+```
196+
197+```
198+> ((at-raw ~[so ni bo]):dejs:format ~[n+'123' s+'foo' b+&])
199+dojo: hoon expression failed
200+```
201+
202+---
203+
204+### `++bo:dejs:format`
205+
206+Boolean
207+
208+Convert boolean `jon` to a `?`.
209+
210+#### Accepts
211+
212+`jon` is a `json` boolean.
213+
214+#### Produces
215+
216+A `?`.
217+
218+#### Source
219+
220+```hoon
221+++ bo
222+ |=(jon=json ?>(?=([%b *] jon) p.jon))
223+```
224+
225+#### Examples
226+
227+```
228+> (bo:dejs:format b+|)
229+%.n
230+```
231+
232+---
233+
234+### `++bu:dejs:format`
235+
236+Boolean NOT
237+
238+Convert the logical NOT of boolean `jon` to a `?`.
239+
240+#### Accepts
241+
242+`jon` is a `json` boolean.
243+
244+#### Produces
245+
246+A `?`.
247+
248+#### Source
249+
250+```hoon
251+++ bu
252+ |=(jon=json ?>(?=([%b *] jon) !p.jon))
253+```
254+
255+#### Examples
256+
257+```
258+> (bu:dejs:format [%b %.y])
259+%.n
260+```
261+
262+---
263+
264+### `++ci:dejs:format`
265+
266+Maybe transform
267+
268+Decode `jon` with `wit`, then transform it with gate `poq` which produces a `unit`. Crash if the `unit` is `~` or else unwrap it and produce its data.
269+
270+The `+ci` function is a wet gate that takes a `poq` and `wit` and produces a new gate that takes `jon`.
271+
272+#### Accepts
273+
274+`poq` is a `gate` that produces a `unit`.
275+
276+`wit` is a `fist`.
277+
278+The wet gate takes `[poq=gate wit=fist]`.
279+
280+`jon` is `json` of the kind accepted by `wit`. `jon` is the sample of the gate produced by the wet gate.
281+
282+#### Produces
283+
284+If gate `poq` produces `(unit [type])`, produce `[type]` or else crash.
285+
286+#### Source
287+
288+```hoon
289+++ ci
290+ |* [poq=gate wit=fist]
291+ |= jon=json
292+ (need (poq (wit jon)))
293+```
294+
295+#### Examples
296+
297+```
298+> ((ci |=(a=? ?:(=(a &) `'foo' ~)) bo):dejs:format b+&)
299+'foo'
300+```
301+
302+```
303+> ((ci |=(a=? ?:(=(a &) `'foo' ~)) bo):dejs:format b+|)
304+dojo: hoon expression failed
305+```
306+
307+---
308+
309+### `++cu:dejs:format`
310+
311+Transform
312+
313+Decode `jon` with `wit`, then transform it with gate `poq`.
314+
315+The `+cu` function is a wet gate that takes `poq` and `wit` and produces a new gate that takes `jon`.
316+
317+#### Accepts
318+
319+`poq` is a `gate`.
320+
321+`wit` is a `fist`.
322+
323+The wet gate takes `[poq=gate wit=fist]`.
324+
325+`jon` is `json` of the kind handled by `wit`. `jon` is the sample of the gate produced by the wet gate.
326+
327+#### Produces
328+
329+The type produced by the gate given in `poq`.
330+
331+#### Source
332+
333+```hoon
334+++ cu
335+ |* [poq=gate wit=fist]
336+ |= jon=json
337+ (poq (wit jon))
338+```
339+
340+#### Examples
341+
342+```
343+> ((cu |=(=@t [t t t]) so):dejs:format s+'foo')
344+['foo' 'foo' 'foo']
345+```
346+
347+---
348+
349+### `++di:dejs:format`
350+
351+Millisecond date
352+
353+Convert number `jon`, containing a Unix milliseconds timestamp, to a date.
354+
355+#### Accepts
356+
357+`jon` is a `json` number.
358+
359+#### Produces
360+
361+A `@da`.
362+
363+#### Source
364+
365+```hoon
366+++ di
367+ (cu from-unix-ms:chrono:userlib ni)
368+```
369+
370+#### Examples
371+
372+```
373+> =time (time:enjs:format now)
374+> time
375+[%n p=~.1630471202176]
376+> (di:dejs:format time)
377+~2021.9.1..04.40.02..2d0e.5604.1893.74bc
378+```
379+
380+---
381+
382+### `++du:dejs:format`
383+
384+Second date
385+
386+Convert number `jon`, containing a Unix seconds timestamp, to a date.
387+
388+#### Accepts
389+
390+`jon` is a `json` number.
391+
392+#### Produces
393+
394+A `@da`.
395+
396+#### Source
397+
398+```hoon
399+++ du
400+ (cu from-unix:chrono:userlib ni)
401+```
402+
403+#### Examples
404+
405+```
406+> =sec (sect:enjs:format now)
407+> sec
408+[%n p=~.1630471524]
409+> (du:dejs:format sec)
410+~2021.9.1..04.45.24
411+```
412+
413+---
414+
415+### `++mu:dejs:format`
416+
417+True unit
418+
419+Decode `jon` with `wit`, then wrap it in a `unit`. Produce `~` if `jon` is `~`.
420+
421+The `+mu` function is a wet gate that takes `wit` and produces a gate which takes `jon`.
422+
423+#### Accepts
424+
425+`wit` is a `fist`.
426+
427+The wet gate takes `wit=fist`.
428+
429+`jon` is `json` of the kind `wit` handles. `jon` is the sample of the gate produced by the wet gate.
430+
431+#### Produces
432+
433+A `(unit [type])`, where `[type]` is the type produced by the `fist` specified in `wit`.
434+
435+#### Source
436+
437+```hoon
438+++ mu
439+ |* wit=fist
440+ |= jon=json
441+ ?~(jon ~ (some (wit jon)))
442+```
443+
444+#### Examples
445+
446+```
447+> ((mu so):dejs:format s+'foo')
448+[~ 'foo']
449+```
450+
451+```
452+> ((mu so):dejs:format ~)
453+~
454+```
455+
456+---
457+
458+### `++ne:dejs:format`
459+
460+Number as real
461+
462+Convert number `jon` to a `@rd`.
463+
464+#### Accepts
465+
466+`jon` is a `json` number.
467+
468+#### Produces
469+
470+A `@rd`.
471+
472+#### Source
473+
474+```hoon
475+++ ne
476+ |= jon=json
477+ ^- @rd
478+ ?> ?=([%n *] jon)
479+ (rash p.jon (cook ryld (cook royl-cell:^so json-rn)))
480+```
481+
482+#### Examples
483+
484+```
485+> (ne:dejs:format n+'123')
486+.~123
487+```
488+
489+```
490+> (ne:dejs:format n+'2.47')
491+.~2.47
492+```
493+
494+---
495+
496+### `++ni:dejs:format`
497+
498+Number as integer
499+
500+Convert number `jon` to a `@ud`. `jon` must be an integer or it will crash.
501+
502+#### Accepts
503+
504+`jon` is a `json` number.
505+
506+#### Produces
507+
508+A `@ud`.
509+
510+#### Source
511+
512+```hoon
513+++ ni
514+ |= jon=json
515+ ?> ?=([%n *] jon)
516+ (rash p.jon dem)
517+```
518+
519+#### Examples
520+
521+```
522+> (ni:dejs:format n+'123')
523+123
524+```
525+
526+```
527+> (ni:dejs:format n+'2.47')
528+{1 2}
529+syntax error
530+```
531+
532+---
533+
534+### `++no:dejs:format`
535+
536+Number as knot
537+
538+Convert number `jon` to a `@ta`.
539+
540+#### Accepts
541+
542+`jon` is a `json` number.
543+
544+#### Produces
545+
546+A `@ta`.
547+
548+#### Source
549+
550+```hoon
551+++ no
552+ |=(jon=json ?>(?=([%n *] jon) p.jon))
553+```
554+
555+#### Examples
556+
557+```
558+> (no:dejs:format n+'2.47')
559+~.2.47
560+```
561+
562+```
563+> (no:dejs:format n+'123')
564+~.123
565+```
566+
567+---
568+
569+### `++nu:dejs:format`
570+
571+Parse string as hex
572+
573+Parse string `jon` as hexadecimal or crash.
574+
575+#### Accepts
576+
577+`jon` is a `json` string.
578+
579+#### Produces
580+
581+A `@`.
582+
583+#### Source
584+
585+```hoon
586+++ nu
587+ |= jon=json
588+ ?> ?=([%s *] jon)
589+ (rash p.jon hex)
590+```
591+
592+#### Examples
593+
594+```
595+> `@ux`(nu:dejs:format s+'DEADBEEF')
596+0xdead.beef
597+```
598+
599+```
600+> `@ux`(nu:dejs:format s+'deadbeef')
601+0xdead.beef
602+```
603+
604+```
605+> `@ux`(nu:dejs:format s+'0xdeadbeef')
606+{1 2}
607+syntax error
608+```
609+
610+---
611+
612+### `++of:dejs:format`
613+
614+Object as frond
615+
616+Convert object `jon`, which contains a single key-value pair, to a key-value tuple using the `fist` in `wer` which matches the key.
617+
618+The `+of` function is a wet gate that takes a list of pairs of keys and `fist`s and produces a new gate that takes `json`.
619+
620+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
621+
622+#### Accepts
623+
624+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless `list`.
625+
626+`jon` is a `json` object containing a single key. `jon` is the sample of the gate produced by the wet gate.
627+
628+#### Produces
629+
630+A `[@t [type]]` where `[type]` is the type produced by the matching `fist`.
631+
632+#### Source
633+
634+```hoon
635+++ of
636+ |* wer=(pole [cord fist])
637+ |= jon=json
638+ ?> ?=([%o [@ *] ~ ~] jon)
639+ |-
640+ ?- wer
641+ :: [[key=@t wit=*] t=*]
642+ [[key=@t *] t=*]
643+ => .(wer [[* wit] *]=wer)
644+ ?: =(key.wer p.n.p.jon)
645+ [key.wer ~|(key+key.wer (wit.wer q.n.p.jon))]
646+ ?~ t.wer ~|(bad-key+p.n.p.jon !!)
647+ ((of t.wer) jon)
648+ ==
649+```
650+
651+#### Examples
652+
653+First, let's store some objects containing key-value pairs:
654+
655+```
656+> =obj-1 o+(malt ['foo' s+'hello']~)
657+> (crip (en-json:html obj-1))
658+'{"foo":"hello"}'
659+```
660+
661+```
662+> =obj-2 o+(malt ~[['bar' a+~[n+'123' n+'456']]])
663+> (crip (en-json:html obj-2))
664+'{"bar":[123,456]}'
665+```
666+
667+```
668+> =obj-3 o+(malt ['baz' b+&]~)
669+> (crip (en-json:html obj-3))
670+'{"baz":true}'
671+```
672+
673+Next, let's construct a `+of` function and try it on our objects:
674+
675+```
676+> ((of ~[foo+so bar+(ar ni)]):dejs:format obj-1)
677+[%'foo' 'hello']
678+```
679+
680+```
681+> ((of ~[foo+so bar+(ar ni)]):dejs:format obj-2)
682+[%'bar' ~[123 456]]
683+```
684+
685+```
686+> ((of ~[foo+so bar+(ar ni)]):dejs:format obj-3)
687+[%bad-key 'baz']
688+dojo: hoon expression failed
689+```
690+
691+---
692+
693+### `++ot:dejs:format`
694+
695+Object as tuple.
696+
697+Convert object `jon` to a tuple by decoding each value with the matching `fist` in `wer`. Each key in `wer` must be matched to a key in `jon`. On the other hand, if there are keys in `jon` with no corresponding key in `wer`, they'll simply be ignored.
698+
699+The `+ot` function is a wet gate that takes a list of key-`fist` pairs, and produces a gate which takes `json`.
700+
701+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
702+
703+#### Accepts
704+
705+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless list.
706+
707+`jon` is a `json` object, and is the sample of the gate produced by the wet gate.
708+
709+#### Produces
710+
711+A tuple where the type of each item is the product of the corresponding `fist` in `wer`. The order of items in the tuple will match the order of items in `wer`.
712+
713+#### Source
714+
715+```hoon
716+++ ot
717+ |* wer=(pole [cord fist])
718+ |= jon=json
719+ ?> ?=([%o *] jon)
720+ ((ot-raw wer) p.jon)
721+```
722+
723+#### Examples
724+
725+```
726+> %- (ot ~[foo+so bar+ni]):dejs:format
727+ o+(malt (limo ~[['bar' n+'123'] ['foo' s+'hello'] ['baz' b+&]]))
728+['hello' 123]
729+```
730+
731+```
732+> %- (ot ~[foo+so bar+ni]):dejs:format
733+ o+(malt (limo ~[['bar' n+'123'] ['baz' b+&]]))
734+[%key 'foo']
735+dojo: hoon expression failed
736+```
737+
738+---
739+
740+### `++ot-raw:dejs:format`
741+
742+Object as tuple, raw
743+
744+This function is used internally by [+ot](#otdejsformat) and would not typically be used directly.
745+
746+`+ot-raw` converts map `jom` to a tuple by decoding each value with the matching `fist` in `wer`. Each key in `wer` must be matched to a key in the given map. On the other hand, if there are keys in the map with no corresponding key in `wer`, they'll simply be ignored.
747+
748+The `+ot-raw` function is a wet gate that takes a list of key-`fist` pairs, and produces a gate which takes a map of keys to `json`.
749+
750+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
751+
752+#### Accepts
753+
754+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless list.
755+
756+`jom` is a `(map @t json)`, and is the sample of the gate produced by the wet gate.
757+
758+#### Produces
759+
760+A tuple where the type of each item is the product of the corresponding `fist` in `wer`. The order of items in the tuple will match the order of items in `wer`.
761+
762+#### Source
763+
764+```hoon
765+++ ot-raw
766+ |* wer=(pole [cord fist])
767+ |= jom=(map @t json)
768+ ?- wer
769+ :: [[key=@t wit=*] t=*]
770+ [[key=@t *] t=*]
771+ => .(wer [[* wit] *]=wer)
772+ =/ ten ~|(key+key.wer (wit.wer (~(got by jom) key.wer)))
773+ ?~(t.wer ten [ten ((ot-raw t.wer) jom)])
774+ ==
775+```
776+
777+#### Examples
778+
779+```
780+> %- (ot-raw ~[foo+so bar+ni]):dejs:format
781+ (malt (limo ~[['bar' n+'123'] ['foo' s+'hello'] ['baz' b+&]]))
782+['hello' 123]
783+```
784+
785+```
786+> %- (ot-raw ~[foo+so bar+ni]):dejs:format
787+ (malt (limo ~[['bar' n+'123'] ['baz' b+&]]))
788+[%key 'foo']
789+dojo: hoon expression failed
790+```
791+
792+---
793+
794+### `++ou:dejs:format`
795+
796+Object of units
797+
798+Convert object `jon` to a tuple by decoding each value with the function in `wer` that matches its key. Keys in `jon` with no matching key in `wer` are ignored. This is the same as [+ot](#otdejsformat) except that:
799+
800+- It wraps each value in `jon` in a `unit` before passing it to the corresponding function in `wer`.
801+- If a key in `wer` has no matching key in `jon`, it passes `~` to that function.
802+
803+Therefore, the functions must take a `(unit json)` rather than just `json`, so they are not `fist`s but rather `$-((unit json) grub)` (despite what the source code says). There are two `+dejs` functions that can be used in `+ou` and take `unit`s: [+uf](#ufdejsformat) and [+un](#undejsformat). Both of them wrap `fist`s like `(uf so)` or `(un so)`. The former, `+uf`, lets you replace a null `unit` with something of your choosing. The latter, `+un`, crashes if the `unit` is null. Using both in a `+ou` allows you to set some values as mandatory and others as optional, replacing any missing optional ones with whatever you want. This is the ultimate purpose of `+ou`.
804+
805+The `+ou` function is a wet gate that takes a list of key-function pairs, and produces a gate which takes `json`.
806+
807+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
808+
809+#### Accepts
810+
811+`wer` is a `(pole [cord $-((unit json) grub)])`, despite saying `(pole [cord fist])` in the source code. `wer` is the sample of the wet gate. A `pole` is a faceless list.
812+
813+`jon` is a `json` object, and is the sample of the gate produced by the wet gate.
814+
815+#### Produces
816+
817+A tuple where the type of each item is the product of the corresponding function in `wer`. The order of items in the tuple will match the order of items in `wer`.
818+
819+#### Source
820+
821+```hoon
822+++ ou
823+ |* wer=(pole [cord fist])
824+ |= jon=json
825+ ?> ?=([%o *] jon)
826+ ((ou-raw wer) p.jon)
827+```
828+
829+#### Examples
830+
831+```
832+> %- (ou ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
833+ o+(malt (limo ~[['foo' s+'hello']]))
834+['hello' %missing]
835+```
836+
837+```
838+> %- (ou ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
839+ o+(malt (limo ~[['bar' n+'123']]))
840+[%key 'foo']
841+dojo: hoon expression failed
842+```
843+
844+```
845+> %- (ou ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
846+ o+(malt (limo ~[['foo' s+'hello'] ['bar' n+'123']]))
847+['hello' 123]
848+```
849+
850+---
851+
852+### `++ou-raw:dejs:format`
853+
854+Object of units, raw
855+
856+This function is used internally by [+ou](#oudejsformat), you would not typically use it directly.
857+
858+Convert map `jom` to a tuple by decoding each value with the function in `wer` that matches its key. Keys in `jom` with no matching key in `wer` are ignored. This is the same as [+ot-raw](#ot-rawdejsformat) except that:
859+
860+- It wraps each value in `jom` in a `unit` before passing it to the corresponding function in `wer`.
861+- If a key in `wer` has no matching key in `jom`, it passes `~` to that function.
862+
863+Therefore, the functions must take a `(unit json)` rather than just `json`, so they are not `fist`s but rather `$-((unit json) grub)` (despite what the source code says). There are two `+dejs` functions that can be used in `+ou-raw` and take `unit`s: [+uf](#ufdejsformat) and [+un](#undejsformat). Both of them wrap `fist`s like `(uf so)` or `(un so)`. The former, `+uf`, lets you replace a null `unit` with something of your choosing. The latter, `+un`, crashes if the `unit` is null. Using both in a `+ou-raw` allows you to set some values as mandatory and others as optional, replacing any missing optional ones with whatever you want.
864+
865+The `+ou-raw` function is a wet gate that takes a list of key-function pairs, and produces a gate which takes a map of `@t` keys to `json`.
866+
867+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
868+
869+#### Accepts
870+
871+`wer` is a `(pole [cord $-((unit json) grub)])`, despite saying `(pole [cord fist])` in the source code. `wer` is the sample of the wet gate. A `pole` is a faceless list.
872+
873+`jon` is a `(map @t json)`, and is the sample of the gate produced by the wet gate.
874+
875+#### Produces
876+
877+A tuple where the type of each item is the product of the corresponding function in `wer`. The order of items in the tuple will match the order of items in `wer`.
878+
879+#### Source
880+
881+```hoon
882+++ ou-raw
883+ |* wer=(pole [cord fist])
884+ |= jom=(map @t json)
885+ ?- wer
886+ :: [[key=@t wit=*] t=*]
887+ [[key=@t *] t=*]
888+ => .(wer [[* wit] *]=wer)
889+ =/ ten ~|(key+key.wer (wit.wer (~(get by jom) key.wer)))
890+ ?~(t.wer ten [ten ((ou-raw t.wer) jom)])
891+ ==
892+```
893+
894+#### Examples
895+
896+```
897+> %- (ou-raw ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
898+ (malt (limo ~[['foo' s+'hello']]))
899+['hello' %missing]
900+```
901+
902+```
903+> %- (ou-raw ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
904+ (malt (limo ~[['bar' n+'123']]))
905+[%key 'foo']
906+dojo: hoon expression failed
907+```
908+
909+```
910+> %- (ou-raw ~[foo+(un so) bar+(uf missing+ni)]):dejs:format
911+ (malt (limo ~[['foo' s+'hello'] ['bar' n+'123']]))
912+['hello' 123]
913+```
914+
915+---
916+
917+### `++oj:dejs:format`
918+
919+Object as jug
920+
921+Convert `jon`, an object of arrays, to a `jug`. Decode each element in each array with `fist`.
922+
923+The `+oj` function is a wet gate that takes `fist` and produces a gate that takes `jon`.
924+
925+#### Accepts
926+
927+`fist` is a `fist`, and is the sample of the wet gate.
928+
929+`jon` is a `json` object of arrays. Each element in each array is of the same `json` kind. `jon` is the sample of the gate produced by the wet gate.
930+
931+#### Produces
932+
933+A `(jug cord [type])`, where `[type]` is the type produced by `fist`.
934+
935+#### Source
936+
937+```hoon
938+++ oj
939+ |* =fist
940+ ^- $-(json (jug cord _(fist *json)))
941+ (om (as fist))
942+```
943+
944+#### Examples
945+
946+```
947+> =jon (need (de-json:html '{"foo":["aaa","bbb","ccc"],"bar":["xxx","yyy","zzz"]}'))
948+> ((oj so):dejs:format jon)
949+{[p='bar' q={'xxx' 'zzz' 'yyy'}] [p='foo' q={'bbb' 'ccc' 'aaa'}]}
950+```
951+
952+---
953+
954+### `++om:dejs:format`
955+
956+Object as map
957+
958+Convert object `jon` to a map, decoding each value with `wit`.
959+
960+The `+om` function is a wet gate that takes `wit` and produces a gate that takes `jon`.
961+
962+#### Accepts
963+
964+`wit` is a `fist`, and is the sample of the wet gate.
965+
966+`jon` is a `json` object whose values are the kind of `json` that `wit` takes. `jon` is the sample of the gate produced by the wet gate.
967+
968+#### Produces
969+
970+A `(map cord [type])`, where `[type]` is the type produced by `wit`.
971+
972+#### Source
973+
974+```hoon
975+++ om
976+ |* wit=fist
977+ |= jon=json
978+ ?> ?=([%o *] jon)
979+ (~(run by p.jon) wit)
980+```
981+
982+#### Examples
983+
984+```
985+> =jon (need (de-json:html '{"foo":"aaa","bar":"bbb"}'))
986+> ((om so):dejs:format jon)
987+{[p='bar' q='bbb'] [p='foo' q='aaa']}
988+```
989+
990+---
991+
992+### `++op:dejs:format`
993+
994+Parse keys of map
995+
996+Convert object `jon` to a map, parsing each key with `fel` and decoding each value with `wit`.
997+
998+The `+op` function is a wet gate that takes `fel` and `wit`, and produces a gate that takes `jon`.
999+
1000+#### Accepts
1001+
1002+The wet gate takes a cell of `[fel wil]`, where `fel` is a parsing `rule` and `wil` is a `fist`.
1003+
1004+`jon` is a `json` object, whose keys are parsable by `fel` and whose values are `json` of the kind `wit` takes. `jon` is the sample of the gate produced by the wet gate.
1005+
1006+#### Produces
1007+
1008+A `(map [a] [b])` where `[a]` is the type produced by `fel` and `[b]` is the type produced by `wit`.
1009+
1010+#### Source
1011+
1012+```hoon
1013+++ op
1014+ |* [fel=rule wit=fist]
1015+ |= jon=json ^- (map _(wonk *fel) _*wit)
1016+ =/ jom ((om wit) jon)
1017+ %- malt
1018+ %+ turn ~(tap by jom)
1019+ |* [a=cord b=*]
1020+ => .(+< [a b]=+<)
1021+ [(rash a fel) b]
1022+```
1023+
1024+#### Examples
1025+
1026+```
1027+> =jon (need (de-json:html '{"123":"aaa","456":"bbb"}'))
1028+> ((op dem so):dejs:format jon)
1029+{[p=456 q='bbb'] [p=123 q='aaa']}
1030+```
1031+
1032+---
1033+
1034+### `++pa:dejs:format`
1035+
1036+String as path
1037+
1038+Convert `jon` and parse to a path.
1039+
1040+#### Accepts
1041+
1042+`jon` is a `json` string encoding a `path`.
1043+
1044+#### Produces
1045+
1046+A `(list @)` which can be cast to a `path`.
1047+
1048+#### Source
1049+
1050+```hoon
1051+++ pa
1052+ (su stap)
1053+```
1054+
1055+#### Examples
1056+
1057+```
1058+> `path`(pa:dejs:format s+'/foo/bar/baz')
1059+/foo/bar/baz
1060+```
1061+
1062+---
1063+
1064+### `++pe:dejs:format`
1065+
1066+Prefix
1067+
1068+Decode `jon` with `wit`, and prefix the result with `pre`.
1069+
1070+The `+pe` function is a wet gate that takes `pre` and `wit`, and produces a gate that takes `jon`.
1071+
1072+#### Accepts
1073+
1074+The wet gate takes a cell of `[pre wit]`, where `pre` is any noun and `wit` is a `fist`.
1075+
1076+`jon` is `json` of the kind accepted by `wit`. `jon` is the sample of the gate produced by the wet gate.
1077+
1078+#### Produces
1079+
1080+A cell of `[[a] [b]]`, where `[a]` is the noun given in `pre` and `[b]` is the type produced by `wit`.
1081+
1082+#### Source
1083+
1084+```hoon
1085+++ pe
1086+ |* [pre=* wit=fist]
1087+ (cu |*(* [pre +<]) wit)
1088+```
1089+
1090+#### Examples
1091+
1092+```
1093+> ((pe %foo so):dejs:format s+'bar')
1094+[%foo 'bar']
1095+```
1096+
1097+---
1098+
1099+### `++sa:dejs:format`
1100+
1101+String as tape
1102+
1103+Convert `jon` to a `tape`.
1104+
1105+#### Accepts
1106+
1107+`jon` is a `json` string.
1108+
1109+#### Produces
1110+
1111+A `tape`.
1112+
1113+#### Source
1114+
1115+```hoon
1116+++ sa
1117+ |=(jon=json ?>(?=([%s *] jon) (trip p.jon)))
1118+```
1119+
1120+#### Examples
1121+
1122+```
1123+> (sa:dejs:format s+'foo')
1124+"foo"
1125+```
1126+
1127+---
1128+
1129+### `++sd:dejs:format`
1130+
1131+String `@ud` as date
1132+
1133+Convert `jon` to a `@da`, parsing it as a date in `@ud` form.
1134+
1135+#### Accepts
1136+
1137+`jon` is a `json` string encoding a date in `@ud` form.
1138+
1139+#### Produces
1140+
1141+A `@da`.
1142+
1143+#### Source
1144+
1145+```hoon
1146+++ sd
1147+ |= jon=json
1148+ ^- @da
1149+ ?> ?=(%s -.jon)
1150+ `@da`(rash p.jon dem:ag)
1151+```
1152+
1153+#### Examples
1154+
1155+```
1156+> (sd:dejs:format s+(scot %ud now))
1157+~2021.9.8..01.02.41..e5db
1158+```
1159+
1160+---
1161+
1162+### `++se:dejs:format`
1163+
1164+String as aura
1165+
1166+Convert and parse `jon` to an atom of the type specified in `aur`.
1167+
1168+The `+se` function is a gate within a gate. The first gate takes `aur` and the second takes `jon`.
1169+
1170+#### Accepts
1171+
1172+`aur` is a `@tas` denoting an aura like `%ud`, `%tas`, `%p`, etc. `aur` is the sample of the first gate
1173+
1174+`jon` is a `json` string encoding an atom of the type specified in `aur`. `jon` is the sample of the second nested gate.
1175+
1176+#### Produces
1177+
1178+A `@` which can then be cast to the type specified in `aur`.
1179+
1180+#### Source
1181+
1182+```hoon
1183+++ se
1184+ |= aur=@tas
1185+ |= jon=json
1186+ ?>(?=([%s *] jon) (slav aur p.jon))
1187+```
1188+
1189+#### Examples
1190+
1191+```
1192+> `@p`((se %p):dejs:format s+(scot %p our))
1193+~zod
1194+```
1195+
1196+```
1197+> `@da`((se %da):dejs:format s+(scot %da now))
1198+~2021.9.8..01.12.28..4f6a
1199+```
1200+
1201+---
1202+
1203+### `++so:dejs:format`
1204+
1205+String as cord
1206+
1207+Convert `jon` to a cord.
1208+
1209+#### Accepts
1210+
1211+`jon` is a `json` string.
1212+
1213+#### Produces
1214+
1215+A `@t`.
1216+
1217+#### Source
1218+
1219+```hoon
1220+++ so
1221+ |=(jon=json ?>(?=([%s *] jon) p.jon))
1222+```
1223+
1224+#### Examples
1225+
1226+```
1227+> (so:dejs:format s+'foo')
1228+'foo'
1229+```
1230+
1231+---
1232+
1233+### `++su:dejs:format`
1234+
1235+Parse string
1236+
1237+Convert and parse `jon` with `sab`.
1238+
1239+The `+su` function is a wet gate that takes `sab`, and produces a gate that takes `jon`.
1240+
1241+#### Accepts
1242+
1243+`sab` is a parsing `rule`, and is the sample of the wet gate.
1244+
1245+`jon` is a `json` string, and is the sample of the gate produced by the wet gate.
1246+
1247+#### Produces
1248+
1249+The type produced by `sab`.
1250+
1251+#### Source
1252+
1253+```hoon
1254+++ su
1255+ |* sab=rule
1256+ |= jon=json ^+ (wonk *sab)
1257+ ?> ?=([%s *] jon)
1258+ (rash p.jon sab)
1259+```
1260+
1261+#### Examples
1262+
1263+```
1264+> ((su dem):dejs:format s+'123456')
1265+123.456
1266+```
1267+
1268+```
1269+> `@ub`((su bin):dejs:format s+'00001011101110001101')
1270+0b1011.1011.1000.1101
1271+```
1272+
1273+---
1274+
1275+### `++uf:dejs:format`
1276+
1277+Unit fall
1278+
1279+Convert the `json` data in unit `jon` with `wit` unless `jon` is `~`, in which case return `def`. Note this deals with `(unit json)` rather than the usual `json`. This would typically be used inside a [+ou](#oudejsformat) function to replace missing values with the given values.
1280+
1281+The `+uf` function is a wet gate that takes `def` and `wit`, and produces a gate that takes `jon`.
1282+
1283+#### Accepts
1284+
1285+The wet gate takes a cell of `[def wit]`, where `def` is any `noun` and `wit` is a `fist`.
1286+
1287+`jon` is a `(unit json)`, and is the sample of the gate produced by the wet gate.
1288+
1289+#### Produces
1290+
1291+Either the type produced by `wit`, or else the `noun` given in `def` if `jon` is null.
1292+
1293+#### Source
1294+
1295+```hoon
1296+++ uf
1297+ |* [def=* wit=fist]
1298+ |= jon=(unit json)
1299+ ?~(jon def (wit u.jon))
1300+```
1301+
1302+#### Examples
1303+
1304+```
1305+> ((uf %missing so):dejs:format `s+'foo')
1306+'foo'
1307+```
1308+
1309+```
1310+> ((uf %missing so):dejs:format ~)
1311+%missing
1312+```
1313+
1314+---
1315+
1316+### `++un:dejs:format`
1317+
1318+Unit need
1319+
1320+Convert the `json` data in unit `jon` with `wit` unless `jon` is `~`, in which case crash. Note this deals with `(unit json)` rather than the usual `json`. This would typically be used inside a [+ou](#oudejsformat) function and in conjunction with [+uf](#ufdejsformat) to specify mandatory values.
1321+
1322+The `+un` function is a wet gate that takes `wit` and produces a gate that takes `jon`.
1323+
1324+#### Accepts
1325+
1326+`wit` is a `fist`, and is the sample of the wet gate.
1327+
1328+`jon` is a `(unit json)`, and is the sample of the gate returned by the wet gate.
1329+
1330+#### Produces
1331+
1332+The type produced by `wit` or crash if `jon` is null.
1333+
1334+#### Source
1335+
1336+```hoon
1337+++ un
1338+ |* wit=fist
1339+ |= jon=(unit json)
1340+ (wit (need jon))
1341+```
1342+
1343+#### Examples
1344+
1345+```
1346+> ((un so):dejs:format `s+'foo')
1347+'foo'
1348+```
1349+
1350+```
1351+> ((un so):dejs:format ~)
1352+dojo: hoon expression failed
1353+```
1354+
1355+---
1356+
1357+### `++ul:dejs:format`
1358+
1359+Null
1360+
1361+Return `~` if `jon` is null or else crash.
1362+
1363+#### Accepts
1364+
1365+`jon` is null `json`.
1366+
1367+#### Produces
1368+
1369+`~` if `jon` is null, otherwise crashes.
1370+
1371+#### Source
1372+
1373+```hoon
1374+++ ul
1375+ |=(jon=json ?~(jon ~ !!))
1376+```
1377+
1378+#### Examples
1379+
1380+```
1381+> (ul:dejs:format ~)
1382+~
1383+```
1384+
1385+```
1386+> (ul:dejs:format b+&)
1387+dojo: hoon expression failed
1388+```
1389+
1390+---
1391+
1392+### `++za:dejs:format`
1393+
1394+Full unit pole
1395+
1396+Check whether all units in list `pod` are non-null. This is used internally by some functions and would not typically be used directly.
1397+
1398+#### Accepts
1399+
1400+`pod` is a `(pole (unit))`. A `pole` is a faceless list.
1401+
1402+#### Produces
1403+
1404+A `?`, which is `%.n` if any of the `unit`s in `pod` are `~`, and `%.y` otherwise.
1405+
1406+#### Source
1407+
1408+```hoon
1409+++ za
1410+ |* pod=(pole (unit))
1411+ ?~ pod &
1412+ ?~ -.pod |
1413+ (za +.pod)
1414+```
1415+
1416+#### Examples
1417+
1418+```
1419+> (za:dejs:format ~[`1 `2 `3 `4])
1420+%.y
1421+```
1422+
1423+```
1424+> (za:dejs:format ~)
1425+%.y
1426+```
1427+
1428+```
1429+> (za:dejs:format ~[`1 `2 ~ `4])
1430+%.n
1431+```
1432+
1433+---
1434+
1435+### `++zl:dejs:format`
1436+
1437+Collapse unit list
1438+
1439+Convert `lut`, a list of units, to a `(unit (list))` by stripping the unit from each item. The resulting unit is null if any of the units in the list are null. This is used internally by some functions, you would not typically use it directly.
1440+
1441+#### Accepts
1442+
1443+A `(list (unit))`.
1444+
1445+#### Produces
1446+
1447+A `(unit (list))` which is null if any of the units in `lut` were null.
1448+
1449+#### Source
1450+
1451+```hoon
1452+++ zl
1453+ |* lut=(list (unit))
1454+ ?. |- ^- ?
1455+ ?~(lut & ?~(i.lut | $(lut t.lut)))
1456+ ~
1457+ %- some
1458+ |-
1459+ ?~ lut ~
1460+ [i=u:+.i.lut t=$(lut t.lut)]
1461+```
1462+
1463+#### Examples
1464+
1465+```
1466+> (zl:dejs:format (limo ~[`1 `2 `3 `4 `5 `6]))
1467+[~ [i=1 t=~[2 3 4 5 6]]]
1468+```
1469+
1470+```
1471+> (zl:dejs:format (limo ~[`1 `2 ~ `4 `5 `6]))
1472+~
1473+```
1474+
1475+---
1476+
1477+### `++zp:dejs:format`
1478+
1479+Unit tuple
1480+
1481+Convert `but`, a list of units, to a tuple by stripping the unit from each item. Crashes if any of the units are null. This is used internally by some functions, you would not typically use it directly.
1482+
1483+#### Accepts
1484+
1485+`but` is a `(pole (unit))`. A `pole` is a faceless list.
1486+
1487+#### Produces
1488+
1489+A tuple containing each unwrapped element from the original list, or crashes if any of the units were null.
1490+
1491+#### Source
1492+
1493+```hoon
1494+++ zp
1495+ |* but=(pole (unit))
1496+ ?~ but !!
1497+ ?~ +.but
1498+ u:->.but
1499+ [u:->.but (zp +.but)]
1500+```
1501+
1502+#### Examples
1503+
1504+```
1505+> (zp:dejs:format ~[`1 `2 `3 `4 `5 `6])
1506+[1 2 3 4 5 6]
1507+```
1508+
1509+```
1510+> (zp:dejs:format ~[`1 `2 ~ `4 `5 `6])
1511+mull-none
1512+dojo: hoon expression failed
1513+```
1514+
1515+---
1516+
1517+### `++zm:dejs:format`
1518+
1519+Collapse unit map
1520+
1521+Strip units from values in `lum`, a map of units. Returns null if any of the units are null. This is used internally by some functions, you would not typically use it directly.
1522+
1523+#### Accepts
1524+
1525+`lum` is a `(map term (unit))`
1526+
1527+#### Produces
1528+
1529+A `(unit (map term [type]))`, where `[type]` is the type the units in `lum` contained. Produces `~` if any of the units were null.
1530+
1531+#### Source
1532+
1533+```hoon
1534+++ zm
1535+ |* lum=(map term (unit))
1536+ ?: (~(rep by lum) |=([[@ a=(unit)] b=_|] |(b ?=(~ a))))
1537+ ~
1538+ (some (~(run by lum) need))
1539+```
1540+
1541+#### Examples
1542+
1543+```
1544+> (zm:dejs:format (malt ~[['foo' `1] ['bar' `2]]))
1545+[~ {[p='bar' q=2] [p='foo' q=1]}]
1546+```
1547+
1548+```
1549+> (zm:dejs:format (malt (limo ~[['foo' `1] ['bar' ~]])))
1550+~
1551+```
content/docs/hoon/reference/zuse/2d_7.mdnew file+1307
@@ -0,0 +1,1307 @@
1++++
2+title = "2d(7): From JSON (unit)"
3+weight = 44
4+template = "doc.html"
5++++
6+
7+## `++dejs-soft:format`
8+
9+Container arm for unitized JSON decoding reparsers
10+
11+The `core` inside this arm contains a large collection of functions for converting `json` data to `unit`s of various kinds. The `json` type is defined in `lull.hoon` as:
12+
13+```hoon
14++$ json :: normal json value
15+ $@ ~ :: null
16+ $% [%a p=(list json)] :: array
17+ [%b p=?] :: boolean
18+ [%o p=(map @t json)] :: object
19+ [%n p=@ta] :: number
20+ [%s p=@t] :: string
21+ == ::
22+```
23+
24+This container arm doesn't do anything by itself. It just contains the core with the rest of the `+dejs-soft` functions which are documented below, plus it defines a couple of things for those functions:
25+
26+```hoon
27+=> |% ++ grub (unit *)
28+ ++ fist $-(json grub)
29+ --
30+```
31+
32+A `fist` is a `gate` which takes `json` and produces a `grub`. Apart from a handful of exceptions, all of the functions below are `fist`s. If the functions below aren't adequate for a particular use case, custom `fist`s can easily be written, as long as they conform to the `$-(json grub)` type definition.
33+
34+A `grub` is just defined as `(unit *)`, and is the type of the product of a `fist`. In the case of `+dejs-soft`, it can be any noun in a `unit`.
35+
36+Keep in mind that `+grub:dejs-soft:format` and `+fist:dejs-soft:format` defined here (and subsequently referred to as simply `fist` and `grub`) are different to `+grub:dejs:format` and `+fist:dejs:format` for the [+dejs](/docs/hoon/reference/zuse/2d_6) functions, which simply return `noun`s rather than `unit`s.
37+
38+---
39+
40+### `++ar:dejs-soft:format`
41+
42+Array as list (in unit)
43+
44+Convert array `jon` to a list, decoding each item in `jon` with `wit`. The result is wrapped in a unit which is null if the decoding failed.
45+
46+The `+ar` function is a wet gate that takes `wit` and produces a new gate which takes `jon`.
47+
48+#### Accepts
49+
50+`wit` is a `fist` and is the sample of the wet gate.
51+
52+`jon` is a `json` array containing the kind of `json` that `wit` handles. `jon` is the sample of the gate produced by the wet gate.
53+
54+#### Produces
55+
56+A `(unit (list [type]))` where `[type]` is the type produced by `wit`. The `unit` is null if decoding fails.
57+
58+#### Source
59+
60+```hoon
61+++ ar
62+ |* wit=fist
63+ |= jon=json
64+ ?. ?=([%a *] jon) ~
65+ %- zl
66+ |-
67+ ?~ p.jon ~
68+ [i=(wit i.p.jon) t=$(p.jon t.p.jon)]
69+```
70+
71+#### Examples
72+
73+```
74+> ((ar so):dejs-soft:format a+~[s+'foo' s+'bar' s+'baz'])
75+[~ [i='foo' t=<|bar baz|>]]
76+```
77+
78+```
79+> ((ar so):dejs-soft:format a+~[n+'123' s+'bar' s+'baz'])
80+~
81+```
82+
83+---
84+
85+### `++at:dejs-soft:format`
86+
87+Array as tuple (in unit)
88+
89+Convert array `jon` to a tuple, decoding each item in the array with the corresponding `fist` in list `wil`. The result is wrapped in a unit which is null if the decoding failed.
90+
91+The `+at` function is a wet gate that takes `wil` and produces a new gate which takes `jon`.
92+
93+#### Accepts
94+
95+`wil` is a `(pole fist)`, and is the sample of the wet gate. A `pole` is a faceless list.
96+
97+`jon` is a `json` array whose elements are the same kinds of `json` accepted by the `fist`s in `wil` and in the same order. `jon` is the sample of the gate produced by the wet gate.
98+
99+#### Produces
100+
101+A `(unit [n])` where `[n]` is a tuple containing items of the same type and in the same order as those produced by the `fist`s in `wil`. The `unit` is null if decoding failed.
102+
103+#### Source
104+
105+```hoon
106+++ at
107+ |* wil=(pole fist)
108+ |= jon=json
109+ ?. ?=([%a *] jon) ~
110+ ?. =((lent wil) (lent p.jon)) ~
111+ =+ raw=((at-raw wil) p.jon)
112+ ?.((za raw) ~ (some (zp raw)))
113+```
114+
115+#### Examples
116+
117+```
118+> ((at ~[so ni bo]):dejs-soft:format a+~[s+'foo' n+'123' b+&])
119+[~ ['foo' 123 %.y]]
120+```
121+
122+```
123+> ((at ~[so ni bo]):dejs-soft:format a+~[n+'123' s+'foo' b+&])
124+~
125+```
126+
127+---
128+
129+### `++at-raw:dejs-soft:format`
130+
131+Array as tuple, raw (unitized)
132+
133+This function is used internally by [+at](#atdejs-softformat) and would not typically be used directly.
134+
135+`+at-raw` converts list `jol` to a new list, decoding each item in the list with the corresponding function in list `wil`. Each item in the list gets wrapped in a unit, and any item whose decoding fails is null.
136+
137+The `+at-raw` function is a wet gate that takes `wil` and produces a new gate which takes `jol`.
138+
139+#### Accepts
140+
141+`wil` is a `(pole fist)`, and the sample of the wet gate. A `pole` is a faceless list.
142+
143+`jol` is a `(list json)` whose items are the same kinds of `json` accepted by the `fist`s in `wil` and in the same order. `jol` is the sample of the gate produced by the wet gate.
144+
145+#### Produces
146+
147+A list of the types and in the same order as those produced by the `fist`s in `wil`. Each item is wrapped in a unit and any item whose decoding fails is null.
148+
149+#### Source
150+
151+```hoon
152+++ at-raw
153+ |* wil=(pole fist)
154+ |= jol=(list json)
155+ ?~ wil ~
156+ :- ?~(jol ~ (-.wil i.jol))
157+ ((at-raw +.wil) ?~(jol ~ t.jol))
158+```
159+
160+#### Examples
161+
162+```
163+> ((at-raw ~[so ni bo]):dejs-soft:format ~[s+'foo' n+'123' b+&])
164+[[~ 'foo'] [~ 123] [~ %.y] ~]
165+```
166+
167+```
168+> ((at-raw ~[so ni bo]):dejs-soft:format ~[s+'foo' b+| b+&])
169+[[~ 'foo'] ~ [~ %.y] ~]
170+```
171+
172+---
173+
174+### `++bo:dejs-soft:format`
175+
176+Boolean (in unit)
177+
178+Convert boolean `jon` to a `?` and wrap the result in a unit. If decoding fails the unit is null.
179+
180+#### Accepts
181+
182+`jon` is a `json` boolean.
183+
184+#### Produces
185+
186+A `?` wrapped in a `unit`. The unit is null if the decoding failed.
187+
188+#### Source
189+
190+```hoon
191+++ bo
192+ |=(jon=json ?.(?=([%b *] jon) ~ [~ u=p.jon]))
193+```
194+
195+#### Examples
196+
197+```
198+> (bo:dejs-soft:format b+|)
199+[~ %.n]
200+```
201+
202+```
203+> (bo:dejs-soft:format n+'123')
204+~
205+```
206+
207+---
208+
209+### `++bu:dejs-soft:format`
210+
211+Boolean NOT (in unit)
212+
213+Convert the logical NOT of boolean `jon` to a `?`. The result is wrapped in a unit, if the decoding fails the unit is null.
214+
215+#### Accepts
216+
217+`jon` is a `json` boolean.
218+
219+#### Produces
220+
221+A `(unit ?)`. The `unit` is `~` if the decoding failed.
222+
223+#### Source
224+
225+```hoon
226+++ bu
227+ |=(jon=json ?.(?=([%b *] jon) ~ [~ u=!p.jon]))
228+```
229+
230+#### Examples
231+
232+```
233+> (bu:dejs-soft:format b+&)
234+[~ %.n]
235+```
236+
237+```
238+> (bu:dejs-soft:format n+'123')
239+~
240+```
241+
242+---
243+
244+### `++ci:dejs-soft:format`
245+
246+Maybe transform (in unit)
247+
248+Decode `jon` with `wit`, then transform it with gate `poq` which produces a unit. If the unit is null or the decoding fails it produces `~`, otherwise it produces the unit.
249+
250+The `+ci` function is a wet gate that takes a `poq` and `wit` and produces a new gate that takes `jon`.
251+
252+#### Accepts
253+
254+The wet gate takes `[poq wit]`, where `poq` is a `gate` that produces a `unit` and `wit` is a `fist`.
255+
256+`jon` is `json` of the kind accepted by `wit`. `jon` is the sample of the gate produced by the wet gate.
257+
258+#### Produces
259+
260+Produces `(unit [type])`, where `[type]` is the type of the data in the `unit` produced by `poq`. The `unit` is `~` if the decoding failed or if the `unit` produced by `poq` is `~`.
261+
262+#### Source
263+
264+```hoon
265+++ ci
266+ |* [poq=gate wit=fist]
267+ |= jon=json
268+ (biff (wit jon) poq)
269+```
270+
271+#### Examples
272+
273+```
274+> ((ci |=(a=? ?:(=(a &) `'foo' ~)) bo):dejs-soft:format b+&)
275+[~ 'foo']
276+```
277+
278+```
279+> ((ci |=(a=? ?:(=(a &) `'foo' ~)) bo):dejs-soft:format b+|)
280+~
281+```
282+
283+```
284+> ((ci |=(a=? ?:(=(a &) `'foo' ~)) bo):dejs-soft:format n+'123')
285+~
286+```
287+
288+---
289+
290+### `++cu:dejs-soft:format`
291+
292+Transform (in unit)
293+
294+Decode `jon` with `wit`, then transform it with gate `poq`. The result is wrapped in a unit, which is null if the decoding failed.
295+
296+The `+cu` function is a wet gate that takes `poq` and `wit` and produces a new gate that takes `jon`.
297+
298+#### Accepts
299+
300+The wet gate takes `[poq wit]`, where `poq` is a `gate` and `wit` is a `fist`.
301+
302+`jon` is `json` of the kind handled by `wit`. `jon` is the sample of the gate produced by the wet gate.
303+
304+#### Produces
305+
306+`(unit [type])`, where `[type]` is the type produced by the gate given in `poq`. The `unit` is `~` if the decoding failed.
307+
308+#### Source
309+
310+```hoon
311+++ cu
312+ |* [poq=gate wit=fist]
313+ |= jon=json
314+ (bind (wit jon) poq)
315+```
316+
317+#### Examples
318+
319+```
320+> ((cu |=(a=? ?:(=(a &) 'foo' ~)) bo):dejs-soft:format b+&)
321+[~ 'foo']
322+```
323+
324+```
325+> ((cu |=(a=? ?:(=(a &) 'foo' ~)) bo):dejs-soft:format b+|)
326+[~ ~]
327+```
328+
329+```
330+> ((cu |=(a=? ?:(=(a &) 'foo' ~)) bo):dejs-soft:format n+'123')
331+~
332+```
333+
334+---
335+
336+### `++da:dejs-soft:format`
337+
338+UTC date (in unit)
339+
340+Convert string `jon` to a `@da`, parsing it as a UTC date & time string, e.g.`'Thu, 09 Sep 2021 05:58:52'`. Note the inclusion of a timezone offset like `+1200` will pass the parser but will be ignored. The result is wrapped in a unit, which is null if decoding or parsing failed.
341+
342+#### Accepts
343+
344+`jon` is a `json` string encoding a UTC date & time string.
345+
346+#### Produces
347+
348+A `@da`.
349+
350+#### Examples
351+
352+```
353+> (da:dejs-soft:format s+'Thu, 09 Sep 2021 05:58:52')
354+[~ ~2021.9.9..05.58.52]
355+```
356+
357+```
358+> (da:dejs-soft:format s+'09 Sep 2021 05:58:52')
359+[~ ~2021.9.9..05.58.52]
360+```
361+
362+```
363+> (da:dejs-soft:format s+'Thu, 09 Sep 2021 05:58:52 +1200')
364+[~ ~2021.9.9..05.58.52]
365+```
366+
367+```
368+> (da:dejs-soft:format s+'gkjeagkja')
369+~
370+```
371+
372+```
373+> (da:dejs-soft:format b+&)
374+~
375+```
376+
377+---
378+
379+### `++dank:dejs-soft:format`
380+
381+Tank (in unit)
382+
383+Convert `jon`, a `json`-encoded `tank`, to a `tank`. The result is wrapped in a unit and is null if decoding failed.
384+
385+#### Accepts
386+
387+`jon` is `json`.
388+
389+#### Produces
390+
391+A `(unit tank)`. The `unit` is `~` if decoding failed.
392+
393+#### Source
394+
395+```hoon
396+++ dank
397+ ^- $-(json (unit tank))
398+ %+ re *tank |. ~+
399+ %- of :~
400+ leaf+sa
401+ palm+(ot style+(ot mid+sa cap+sa open+sa close+sa ~) lines+(ar dank) ~)
402+ rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
403+ ==
404+```
405+
406+#### Examples
407+
408+```
409+> =js-txt '{"rose":{"lines":[{"leaf":"foo"},{"leaf":"bar"},{"leaf":"baz"}],"style":{"mid":" ","close":"]","open":"["}}}'
410+> (dank:dejs-soft:format (need (de-json:html js-txt)))
411+[~ [%rose p=[p=" " q="[" r="]"] q=~[[%leaf p="foo"] [%leaf p="bar"] [%leaf p="baz"]]]]
412+> ~(ram re (need (dank:dejs-soft:format (need (de-json:html js-txt)))))
413+"[foo bar baz]"
414+```
415+
416+```
417+> (dank:dejs-soft:format (need (de-json:html '{"leaf":"foo"}')))
418+[~ [%leaf p="foo"]]
419+> ~(ram re (need (dank:dejs-soft:format (need (de-json:html '{"leaf":"foo"}')))))
420+"foo"
421+```
422+
423+```
424+> (dank:dejs-soft:format n+'123')
425+~
426+```
427+
428+---
429+
430+### `++di:dejs-soft:format`
431+
432+Millisecond date (in unit)
433+
434+Convert number `jon` containing milliseconds to a date. The result is wrapped in a unit which is null if decoding failed.
435+
436+#### Accepts
437+
438+`jon` is a `json` number.
439+
440+#### Produces
441+
442+A `(unit @da)`. The `unit` is `~` if decoding failed.
443+
444+#### Source
445+
446+```hoon
447+++ di
448+ (cu from-unix-ms:chrono:userlib ni)
449+```
450+
451+#### Examples
452+
453+```
454+> =time (time:enjs:format now)
455+> time
456+[%n p=~.1631177855330]
457+> (di:dejs-soft:format time)
458+[~ ~2021.9.9..08.57.35..547a.e147.ae14.7ae1]
459+```
460+
461+```
462+> (di:dejs-soft:format b+&)
463+~
464+```
465+
466+---
467+
468+### `++mu:dejs-soft:format`
469+
470+True unit (in unit)
471+
472+Decode `jon` with `wit`, then wrap it in two units. The inner unit is null if `jon` was null, the outer unit is null if decoding failed.
473+
474+The `+mu` function is a wet gate that takes `wit` and produces a gate which takes `jon`.
475+
476+#### Accepts
477+
478+`wit` is a `fist`, and is the sample of the wet gate.
479+
480+`jon` is `json` of the kind `wit` handles. `jon` is the sample of the gate produced by the wet gate.
481+
482+#### Produces
483+
484+A `(unit (unit [type]))`, where `[type]` is the type produced by `wit`. The inner `unit` is `~` if `jon` was null, the outer `unit` is `~` if decoding failed.
485+
486+#### Source
487+
488+```hoon
489+++ mu
490+ |* wit=fist
491+ |= jon=json
492+ ?~(jon (some ~) (bind (wit jon) some))
493+```
494+
495+#### Examples
496+
497+```
498+> ((mu so):dejs-soft:format s+'foo')
499+[~ [~ u='foo']]
500+```
501+
502+```
503+> ((mu so):dejs-soft:format ~)
504+[~ u=~]
505+```
506+
507+```
508+> ((mu so):dejs-soft:format b+&)
509+~
510+```
511+
512+---
513+
514+### `++ne:dejs-soft:format`
515+
516+Number as real (in unit)
517+
518+Convert number `jon` to a `@rd` and wrap the result in a unit. The unit is null if decoding failed.
519+
520+#### Accepts
521+
522+`jon` is a `json` number.
523+
524+#### Produces
525+
526+A `(unit @rd)`. The `unit` is `~` if decoding failed.
527+
528+#### Source
529+
530+```hoon
531+++ ne
532+ |= jon=json
533+ ^- (unit @rd)
534+ ?. ?=([%n *] jon) ~
535+ (rush p.jon (cook ryld (cook royl-cell:^so json-rn)))
536+```
537+
538+#### Examples
539+
540+```
541+> (ne:dejs-soft:format n+'123')
542+[~ .~123]
543+```
544+
545+```
546+> (ne:dejs-soft:format n+'2.47')
547+[~ .~2.47]
548+```
549+
550+```
551+> (ne:dejs-soft:format b+&)
552+~
553+```
554+
555+---
556+
557+### `++ni:dejs-soft:format`
558+
559+Number as integer (in unit)
560+
561+Convert number `jon` to a `@ud` and wrap it in a unit. If `jon` is not an integer or if decoding otherwise failed, the unit is null.
562+
563+#### Accepts
564+
565+`jon` is a `json` number.
566+
567+#### Produces
568+
569+A `(unit @ud)`. The `unit` is `~` if `jon` was not an integer or if decoding otherwise failed.
570+
571+#### Source
572+
573+```hoon
574+++ ni
575+ |= jon=json
576+ ?. ?=([%n *] jon) ~
577+ (rush p.jon dem)
578+```
579+
580+#### Examples
581+
582+```
583+> (ni:dejs-soft:format n+'123')
584+[~ 123]
585+```
586+
587+```
588+> (ni:dejs-soft:format n+'2.47')
589+~
590+```
591+
592+```
593+> (ni:dejs-soft:format b+&)
594+~
595+```
596+
597+---
598+
599+### `++no:dejs-soft:format`
600+
601+Number as knot (in unit)
602+
603+Convert number `jon` to a `@ta` and wrap it in a unit. The result is null if decoding failed.
604+
605+#### Accepts
606+
607+`jon` is a `json` number.
608+
609+#### Produces
610+
611+A `(unit @ta)`. The `unit` is `~` if decoding failed.
612+
613+#### Source
614+
615+```hoon
616+++ no
617+ |= jon=json
618+ ?. ?=([%n *] jon) ~
619+ (some p.jon)
620+```
621+
622+#### Examples
623+
624+```
625+> (no:dejs-soft:format n+'2.47')
626+[~ ~.2.47]
627+```
628+
629+```
630+> (no:dejs-soft:format n+'123')
631+[~ ~.123]
632+```
633+
634+```
635+> (no:dejs-soft:format b+&)
636+~
637+```
638+
639+---
640+
641+### `++of:dejs-soft:format`
642+
643+Object as frond (in unit)
644+
645+Convert object `jon`, which contains a single key-value pair, to a key-value tuple using the `fist` in `wer` which matches the key. The result is wrapped in a unit which is null if the key couldn't be found in `wer` or if the decoding failed.
646+
647+The `+of` function is a wet gate that takes a list of pairs of keys and `fist`s and produces a new gate that takes `json`.
648+
649+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
650+
651+#### Accepts
652+
653+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless `list`.
654+
655+`jon` is a `json` object containing a single key. `jon` is the sample of the gate produced by the wet gate.
656+
657+#### Produces
658+
659+A `(unit [@t [type]])` where `[type]` is the type produced by the matching `fist`. The `unit` is `~` if decoding failed or the key could not be found.
660+
661+#### Source
662+
663+```hoon
664+++ of
665+ |* wer=(pole [cord fist])
666+ |= jon=json
667+ ?. ?=([%o [@ *] ~ ~] jon) ~
668+ |-
669+ ?~ wer ~
670+ ?: =(-.-.wer p.n.p.jon)
671+ ((pe -.-.wer +.-.wer) q.n.p.jon)
672+ ((of +.wer) jon)
673+```
674+
675+#### Examples
676+
677+First, let's store some objects containing key-value pairs:
678+
679+```
680+> =obj-1 o+(malt ['foo' s+'hello']~)
681+> (crip (en-json:html obj-1))
682+'{"foo":"hello"}'
683+```
684+
685+```
686+> =obj-2 o+(malt ~[['bar' a+~[n+'123' n+'456']]])
687+> (crip (en-json:html obj-2))
688+'{"bar":[123,456]}'
689+```
690+
691+```
692+> =obj-3 o+(malt ['baz' b+&]~)
693+> (crip (en-json:html obj-3))
694+'{"baz":true}'
695+```
696+
697+Next, let's construct a `+of` function and try it on our objects:
698+
699+```
700+> ((of ~[foo+so bar+(ar ni)]):dejs-soft:format obj-1)
701+[~ [%foo 'hello']]
702+```
703+
704+```
705+> ((of ~[foo+so bar+(ar ni)]):dejs-soft:format obj-2)
706+[~ [%bar [i=123 t=~[456]]]]
707+```
708+
709+```
710+> ((of ~[foo+so bar+(ar ni)]):dejs-soft:format obj-3)
711+~
712+```
713+
714+```
715+> ((of ~[foo+so bar+(ar ni)]):dejs-soft:format b+&)
716+~
717+```
718+
719+---
720+
721+### `++ot:dejs-soft:format`
722+
723+Object as tuple (in unit)
724+
725+Convert object `jon` to a tuple by decoding each value with the matching `fist` in `wer`. Each key in `wer` must be matched to a key in `jon`. On the other hand, if there are keys in `jon` with no corresponding key in `wer`, they'll simply be ignored. The result is wrapped in a unit which is null if decoding failed.
726+
727+The `+ot` function is a wet gate that takes a list of key-`fist` pairs, and produces a gate which takes `json`.
728+
729+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
730+
731+#### Accepts
732+
733+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless list.
734+
735+`jon` is a `json` object, and is the sample of the gate produced by the wet gate.
736+
737+#### Produces
738+
739+A `(unit [tuple])` where the type of each item in `[tuple]` is the product of the corresponding `fist` in `wer`. The order of items in the tuple will match the order of items in `wer`. The `unit` is `~` if decoding failed.
740+
741+#### Source
742+
743+```hoon
744+++ ot
745+ |* wer=(pole [cord fist])
746+ |= jon=json
747+ ?. ?=([%o *] jon) ~
748+ =+ raw=((ot-raw wer) p.jon)
749+ ?.((za raw) ~ (some (zp raw)))
750+```
751+
752+#### Examples
753+
754+```
755+> %- (ot ~[foo+so bar+ni]):dejs-soft:format
756+ o+(malt (limo ~[['bar' n+'123'] ['foo' s+'hello'] ['baz' b+&]]))
757+[~ ['hello' 123]]
758+```
759+
760+```
761+> %- (ot ~[foo+so bar+ni]):dejs-soft:format
762+ o+(malt (limo ~[['bar' n+'123'] ['baz' b+&]]))
763+~
764+```
765+
766+---
767+
768+### `++ot-raw:dejs-soft:format`
769+
770+Object as list of units, raw
771+
772+This function is used internally by [+ot](#otdejs-softformat) and would not typically be used directly.
773+
774+`+ot-raw` converts map `jom` to a list of units by decoding each value with the matching `fist` in `wer`, then wrapping them in a unit. Any key in `wer` which cannot be matched to a key in `jon` is null in the resulting list. If there are keys in `jom` with no corresponding key in `wer`, they'll simply be ignored.
775+
776+The `+ot-raw` function is a wet gate that takes a list of key-`fist` pairs, and produces a gate which takes a map of keys to `json`.
777+
778+**Note:** While technically the type of an item in the list `wer` is specified as `[cord fist]`, actually using a `cord` may result in incorrect type inferrence. Instead, you'll want to format it as a `@tas` like `%foo`, so the type system correctly interprets it as a tagged union. If the key contains characters that would be invalid in an ordinary `@tas`, you can format it like `%'foo_bar'` - a `%` then single quotes.
779+
780+#### Accepts
781+
782+`wer` is a `(pole [cord fist])`, and is the sample of the wet gate. A `pole` is a faceless list.
783+
784+`jom` is a `(map @t json)`, and is the sample of the gate produced by the wet gate.
785+
786+#### Produces
787+
788+A `(list (unit))`, where the type of the data in each `unit` is the product of the corresponding `fist` in `wer`. The order of items in the list will match the order of items in `wer`. Any keys in `wer` which couldn't be matched will be `~` in the resulting list.
789+
790+#### Source
791+
792+```hoon
793+++ ot-raw
794+ |* wer=(pole [cord fist])
795+ |= jom=(map @t json)
796+ ?~ wer ~
797+ =+ ten=(~(get by jom) -.-.wer)
798+ [?~(ten ~ (+.-.wer u.ten)) ((ot-raw +.wer) jom)]
799+```
800+
801+#### Examples
802+
803+```
804+> %- (ot-raw ~[foo+so bar+ni]):dejs-soft:format
805+ (malt (limo ~[['bar' n+'123'] ['foo' s+'hello'] ['baz' b+&]]))
806+[[~ 'hello'] [~ 123] ~]
807+```
808+
809+```
810+> %- (ot-raw ~[foo+so bar+ni]):dejs-soft:format
811+ (malt (limo ~[['bar' n+'123'] ['baz' b+&]]))
812+[~ [~ 123] ~]
813+```
814+
815+---
816+
817+### `++om:dejs-soft:format`
818+
819+Object as map (in unit)
820+
821+Convert object `jon` to a map, decoding each value with `wit`. The result is wrapped in a unit which is null if decoding failed.
822+
823+The `+om` function is a wet gate that takes `wit` and produces a gate that takes `jon`.
824+
825+#### Accepts
826+
827+`wit` is a `fist`, and is the sample of the wet gate.
828+
829+`jon` is a `json` object whose values are the kind of `json` that `wit` takes. `jon` is the sample of the gate produced by the wet gate.
830+
831+#### Produces
832+
833+A `(unit (map @t [type]))`, where `[type]` is the type produced by `wit`. The `unit` is `~` if decoding failed.
834+
835+#### Source
836+
837+```hoon
838+++ om
839+ |* wit=fist
840+ |= jon=json
841+ ?. ?=([%o *] jon) ~
842+ (zm (~(run by p.jon) wit))
843+```
844+
845+#### Examples
846+
847+```
848+> =jon (need (de-json:html '{"foo":"aaa","bar":"bbb"}'))
849+> ((om so):dejs-soft:format jon)
850+[~ {[p='bar' q='bbb'] [p='foo' q='aaa']}]
851+```
852+
853+```
854+> ((om so):dejs-soft:format b+&)
855+~
856+```
857+
858+---
859+
860+### `++op:dejs-soft:format`
861+
862+Parse keys of map (in unit)
863+
864+Convert object `jon` to a map, parsing each key with `fel` and decoding each value with `wit`. The result is wrapped in a unit which is null if decoding or parsing failed.
865+
866+The `+op` function is a wet gate that takes `fel` and `wit`, and produces a gate that takes `jon`.
867+
868+#### Accepts
869+
870+The wet gate takes a cell of `[fel wil]`, where `fel` is a parsing `rule` and `wil` is a `fist`.
871+
872+`jon` is a `json` object, whose keys are parsable by `fel` and whose values are `json` of the kind `wit` takes. `jon` is the sample of the gate produced by the wet gate.
873+
874+#### Produces
875+
876+A `(unit (map [a] [b]))` where `[a]` is the type produced by `fel` and `[b]` is the type produced by `wit`. The `unit` is `~` if decoding or parsing failed.
877+
878+#### Source
879+
880+```hoon
881+++ op
882+ |* [fel=rule wit=fist]
883+ |= jon=json ^- (map _(wonk *fel) _*wit)
884+ =/ jom ((om wit) jon)
885+ %- malt
886+ %+ turn ~(tap by jom)
887+ |* [a=cord b=*]
888+ => .(+< [a b]=+<)
889+ [(rash a fel) b]
890+```
891+
892+#### Examples
893+
894+```
895+> =jon (need (de-json:html '{"123":"aaa","456":"bbb"}'))
896+> ((op dem so):dejs-soft:format jon)
897+[~ u={[p=456 q='bbb'] [p=123 q='aaa']}]
898+```
899+
900+---
901+
902+### `++pe:dejs-soft:format`
903+
904+Prefix (in unit)
905+
906+Decode `jon` with `wit`, prefix it with `pre`, then wrap the result in a unit which is null if decoding failed.
907+
908+The `+pe` function is a wet gate that takes `pre` and `wit`, and produces a gate that takes `jon`.
909+
910+#### Accepts
911+
912+The wet gate takes a cell of `[pre wit]`, where `pre` is any noun and `wit` is a `fist`.
913+
914+`jon` is `json` of the kind accepted by `wit`. `jon` is the sample of the gate produced by the wet gate.
915+
916+#### Produces
917+
918+A `(unit [[a] [b]])`, where `[a]` is the noun given in `pre` and `[b]` is the type produced by `wit`. The `unit` is `~` if decoding failed.
919+
920+#### Source
921+
922+```hoon
923+++ pe
924+ |* [pre=* wit=fist]
925+ (cu |*(* [pre +<]) wit)
926+```
927+
928+#### Examples
929+
930+```
931+> ((pe %foo so):dejs-soft:format s+'abc')
932+[~ [%foo 'abc']]
933+```
934+
935+```
936+> ((pe %foo so):dejs-soft:format b+&)
937+~
938+```
939+
940+---
941+
942+### `++re:dejs-soft:format`
943+
944+Recursive reparser
945+
946+This function facilitates recursion in other `fist`s. It is used internally by some functions and would not typically be used directly. `jon` is decoded by the `fist` in the trap `sef` and cast to the type of the noun given in `gar`. The result is wrapped in a unit which is null if decoding failed.
947+
948+`+re` is a wet gate that takes a cell of `gar` and `sef`, and produces a gate which takes `jon`.
949+
950+#### Accepts
951+
952+`gar` is any `noun`, its type determines the return type.
953+
954+`sef` is a `|.(fist)`.
955+
956+The wet gate takes `[gar sef]`.
957+
958+`jon` is `json` of the kind handled by the `fist` in `sef`, and is the sample of the gate produced by the wet gate.
959+
960+#### Produces
961+
962+A `(unit [type])` where `[type]` is the type of `gar`.
963+
964+#### Source
965+
966+```hoon
967+++ re
968+ |* [gar=* sef=_|.(fist)]
969+ |= jon=json
970+ ^- (unit _gar)
971+ ((sef) jon)
972+```
973+
974+#### Examples
975+
976+The basic format looks like so:
977+
978+```
979+> ((re *@t |.(so)):dejs-soft:format s+'abc')
980+[~ 'abc']
981+```
982+
983+```
984+> ((re *@t |.(so)):dejs-soft:format b+&)
985+~
986+```
987+
988+For a recursive example, see its usage in the source of [+dank](#dankdejs-softformat).
989+
990+---
991+
992+### `++sa:dejs-soft:format`
993+
994+String as tape (in unit)
995+
996+Convert `jon` to a `tape` and wrap the result in a unit, which is null if the decoding failed.
997+
998+#### Accepts
999+
1000+`jon` is a `json` string.
1001+
1002+#### Produces
1003+
1004+A `(unit tape)`. The `unit` is `~` if decoding failed.
1005+
1006+#### Source
1007+
1008+```hoon
1009+++ sa
1010+ |= jon=json
1011+ ?.(?=([%s *] jon) ~ (some (trip p.jon)))
1012+```
1013+
1014+#### Examples
1015+
1016+```
1017+> (sa:dejs-soft:format s+'foo')
1018+[~ "foo"]
1019+```
1020+
1021+```
1022+> (sa:dejs-soft:format b+&)
1023+~
1024+```
1025+
1026+---
1027+
1028+### `++so:dejs-soft:format`
1029+
1030+String as cord (in unit)
1031+
1032+Convert `jon` to a cord and wrap it in a unit. The unit is null if decoding failed.
1033+
1034+#### Accepts
1035+
1036+`jon` is a `json` string.
1037+
1038+#### Produces
1039+
1040+A `(unit @t)`. The `unit` is `~` if decoding failed.
1041+
1042+#### Source
1043+
1044+```hoon
1045+++ so
1046+ |= jon=json
1047+ ?.(?=([%s *] jon) ~ (some p.jon))
1048+```
1049+
1050+#### Examples
1051+
1052+```
1053+> (so:dejs-soft:format s+'foo')
1054+[~ 'foo']
1055+```
1056+
1057+```
1058+> (so:dejs-soft:format b+&)
1059+~
1060+```
1061+
1062+---
1063+
1064+### `++su:dejs-soft:format`
1065+
1066+Parse string (in unit)
1067+
1068+Convert and parse `jon` with `sab`, then wrap the result in a unit. The unit is null if parsing or decoding failed.
1069+
1070+The `+su` function is a wet gate that takes `sab`, and produces a gate that takes `jon`.
1071+
1072+#### Accepts
1073+
1074+`sab` is a parsing `rule`, and is the sample of the wet gate.
1075+
1076+`jon` is a `json` string, and is the sample of the gate produced by the wet gate.
1077+
1078+#### Produces
1079+
1080+A `(unit [type])`, where `[type]` is the type produced by `sab`.
1081+
1082+#### Source
1083+
1084+```hoon
1085+++ su
1086+ |* sab=rule
1087+ |= jon=json
1088+ ?. ?=([%s *] jon) ~
1089+ (rush p.jon sab)
1090+```
1091+
1092+#### Examples
1093+
1094+```
1095+> ((su dem):dejs-soft:format s+'123456')
1096+[~ 123.456]
1097+```
1098+
1099+```
1100+> `(unit @ub)`((su bin):dejs-soft:format s+'00001011101110001101')
1101+[~ 0b1011.1011.1000.1101]
1102+```
1103+
1104+```
1105+> ((su dem):dejs-soft:format s+'abc')
1106+~
1107+```
1108+
1109+```
1110+> ((su dem):dejs-soft:format b+&)
1111+~
1112+```
1113+
1114+---
1115+
1116+### `++ul:dejs-soft:format`
1117+
1118+Null (in unit)
1119+
1120+Return `[~ ~]` if `jon` is null or else return `~`.
1121+
1122+#### Accepts
1123+
1124+`jon` is null `json`.
1125+
1126+#### Produces
1127+
1128+A `(unit ~)`. The `unit` is `~` if `jon` is not `~`.
1129+
1130+#### Source
1131+
1132+```hoon
1133+++ ul |=(jon=json ?~(jon (some ~) ~))
1134+```
1135+
1136+#### Examples
1137+
1138+```
1139+> (ul:dejs-soft:format ~)
1140+[~ ~]
1141+```
1142+
1143+```
1144+> (ul:dejs-soft:format b+&)
1145+~
1146+```
1147+
1148+### `++za:dejs-soft:format`
1149+
1150+Full unit pole
1151+
1152+Check whether all units in list `pod` are non-null. This is used internally by some functions and would not typically be used directly.
1153+
1154+#### Accepts
1155+
1156+`pod` is a `(pole (unit))`. A `pole` is a faceless list.
1157+
1158+#### Produces
1159+
1160+A `?`, which is `%.n` if any of the `unit`s in `pod` are `~`, and `%.y` otherwise.
1161+
1162+#### Source
1163+
1164+```hoon
1165+++ za
1166+ |* pod=(pole (unit))
1167+ ?~ pod &
1168+ ?~ -.pod |
1169+ (za +.pod)
1170+```
1171+
1172+#### Examples
1173+
1174+```
1175+> (za:dejs-soft:format ~[`1 `2 `3 `4])
1176+%.y
1177+```
1178+
1179+```
1180+> (za:dejs-soft:format ~)
1181+%.y
1182+```
1183+
1184+```
1185+> (za:dejs-soft:format ~[`1 `2 ~ `4])
1186+%.n
1187+```
1188+
1189+---
1190+
1191+### `++zl:dejs-soft:format`
1192+
1193+Collapse unit list
1194+
1195+Convert `lut`, a list of units, to a `(unit (list))` by stripping the unit from each item. The resulting unit is null if any of the units in the list are null. This is used internally by some functions, you would not typically use it directly.
1196+
1197+#### Accepts
1198+
1199+A `(list (unit))`.
1200+
1201+#### Produces
1202+
1203+A `(unit (list))` which is null if any of the units in `lut` were null.
1204+
1205+#### Source
1206+
1207+```hoon
1208+++ zl
1209+ |* lut=(list (unit))
1210+ ?. |- ^- ?
1211+ ?~(lut & ?~(i.lut | $(lut t.lut)))
1212+ ~
1213+ %- some
1214+ |-
1215+ ?~ lut ~
1216+ [i=u:+.i.lut t=$(lut t.lut)]
1217+```
1218+
1219+#### Examples
1220+
1221+```
1222+> (zl:dejs-soft:format (limo ~[`1 `2 `3 `4 `5 `6]))
1223+[~ [i=1 t=~[2 3 4 5 6]]]
1224+```
1225+
1226+```
1227+> (zl:dejs-soft:format (limo ~[`1 `2 ~ `4 `5 `6]))
1228+~
1229+```
1230+
1231+---
1232+
1233+### `++zp:dejs-soft:format`
1234+
1235+Unit tuple
1236+
1237+Convert `but`, a list of units, to a tuple by stripping the unit from each item. Crashes if any of the units are null. This is used internally by some functions, you would not typically use it directly.
1238+
1239+#### Accepts
1240+
1241+`but` is a `(pole (unit))`. A `pole` is a faceless list.
1242+
1243+#### Produces
1244+
1245+A tuple containing each unwrapped element from the original list, or crashes if any of the units were null.
1246+
1247+#### Source
1248+
1249+```hoon
1250+++ zp
1251+ |* but=(pole (unit))
1252+ ?~ but !!
1253+ ?~ +.but
1254+ u:->.but
1255+ [u:->.but (zp +.but)]
1256+```
1257+
1258+#### Examples
1259+
1260+```
1261+> (zp:dejs-soft:format ~[`1 `2 `3 `4 `5 `6])
1262+[1 2 3 4 5 6]
1263+```
1264+
1265+```
1266+> (zp:dejs-soft:format ~[`1 `2 ~ `4 `5 `6])
1267+mull-none
1268+dojo: hoon expression failed
1269+```
1270+
1271+---
1272+
1273+### `++zm:dejs-soft:format`
1274+
1275+Collapse unit map
1276+
1277+Strip units from values in `lum`, a map of units. Returns null if any of the units are null. This is used internally by some functions, you would not typically use it directly.
1278+
1279+#### Accepts
1280+
1281+`lum` is a `(map term (unit))`
1282+
1283+#### Produces
1284+
1285+A `(unit (map term [type]))`, where `[type]` is the type the units in `lum` contained. Produces `~` if any of the units were null.
1286+
1287+#### Source
1288+
1289+```hoon
1290+++ zm
1291+ |* lum=(map term (unit))
1292+ ?: (~(rep by lum) |=([[@ a=(unit)] b=_|] |(b ?=(~ a))))
1293+ ~
1294+ (some (~(run by lum) need))
1295+```
1296+
1297+#### Examples
1298+
1299+```
1300+> (zm:dejs-soft:format (malt ~[['foo' `1] ['bar' `2]]))
1301+[~ {[p='bar' q=2] [p='foo' q=1]}]
1302+```
1303+
1304+```
1305+> (zm:dejs-soft:format (malt (limo ~[['foo' `1] ['bar' ~]])))
1306+~
1307+```
content/docs/hoon/reference/zuse/2e_2-3.mdnew file+67
@@ -0,0 +1,67 @@
1++++
2+title = "2e(2-3): Print & Parse JSON"
3+weight = 50
4+template = "doc.html"
5++++
6+
7+## `++en-json:html`
8+
9+Print json
10+
11+Encode `val`, a `json` structure, in a `tape`.
12+
13+#### Accepts
14+
15+`val` is any `json`.
16+
17+#### Produces
18+
19+A `tape`.
20+
21+#### Source
22+
23+This is a very large function, refer to `zuse.hoon` for the source code.
24+
25+#### Examples
26+
27+```
28+> (en-json:html s+'foo')
29+"\"foo\""
30+```
31+
32+```
33+> (en-json:html o+(malt (limo ~[['foo' s+'xxx'] ['bar' n+'123'] ['baz' b+&]])))
34+"\{\"foo\":\"xxx\",\"baz\":true,\"bar\":123}"
35+```
36+
37+---
38+
39+## `++de-json:html`
40+
41+Parse json
42+
43+Parse cord `a` to a `json` structure. The result is wrapped in a unit which is null if parsing failed.
44+
45+#### Accepts
46+
47+`a` is a `cord` in which JSON is encoded.
48+
49+#### Produces
50+
51+A `(unit json)`. The `unit` is `~` if parsing failed.
52+
53+#### Source
54+
55+This is a very large function, refer to `zuse.hoon` for the source code.
56+
57+#### Examples
58+
59+```
60+> (de-json:html '{"foo":"xxx","baz":true,"bar":123}')
61+[~ [%o p={[p='bar' q=[%n p=~.123]] [p='baz' q=[%b p=%.y]] [p='foo' q=[%s p='xxx']]}]]
62+```
63+
64+```
65+> (de-json:html '"foo"')
66+[~ [%s p='foo']]
67+```
content/docs/hoon/reference/zuse/_index.mdnew file+31
@@ -0,0 +1,31 @@
1++++
2+title = "Zuse"
3+weight = 50
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6+insert_anchor_links = "right"
7++++
8+
9+Documentation for the `zuse.hoon` library.
10+
11+[Table of Contents](/docs/hoon/reference/zuse/table-of-contents)
12+
13+### 2d: Formatting functions
14+
15+[2d(1-5): To JSON, Wains](/docs/hoon/reference/zuse/2d_1-5)
16+
17+Functions for encoding/decoding line-lists and various JSON encoding functions.
18+
19+[2d(6): From JSON](/docs/hoon/reference/zuse/2d_6)
20+
21+Functions for decoding `json`.
22+
23+[2d(7): From JSON (unit)](/docs/hoon/reference/zuse/2d_7)
24+
25+Functions for decoding `json` to `unit`s.
26+
27+### 2e: Web Text Functions
28+
29+[2e(2-3): Print & Parse JSON](/docs/hoon/reference/zuse/2e_2-3)
30+
31+Print `json` and parse JSON.
content/docs/hoon/reference/zuse/table-of-contents.mdnew file+247
@@ -0,0 +1,247 @@
1++++
2+title = "Table of Contents"
3+weight = 0
4+sort_by = "weight"
5+template = "doc.html"
6++++
7+
8+Documentation for the Zuse library.
9+
10+Can be navigated [alphabetically](#alphabetical) or [by section](#by-section).
11+
12+## Alphabetical
13+
14+### a
15+
16+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ardejs-softformat' title="Decode json (unit): Array as list"><code>++ar:dejs-soft:format</code></a>
17+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ardejsformat' title="Decode json: Array as list"><code>++ar:dejs:format</code></a>
18+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#asdejsformat' title="Decode json: Array as set"><code>++as:dejs:format</code></a>
19+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#at-rawdejs-softformat' title="Decode json (unit): Array as tuple, raw"><code>++at-raw:dejs-soft:format</code></a>
20+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#at-rawdejsformat' title="Decode json: Array as tuple, raw"><code>++at-raw:dejs:format</code></a>
21+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#atdejs-softformat' title="Decode json (unit): Array as tuple"><code>++at:dejs-soft:format</code></a>
22+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#atdejsformat' title="Decode json: Array as tuple"><code>++at:dejs:format</code></a>
23+
24+### b
25+
26+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#bodejs-softformat' title="Decode json (unit): Boolean"><code>++bo:dejs-soft:format</code></a>
27+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#bodejsformat' title="Decode json: Boolean"><code>++bo:dejs:format</code></a>
28+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#budejs-softformat' title="Decode json (unit): Boolean NOT"><code>++bu:dejs-soft:format</code></a>
29+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#budejsformat' title="Decode json: Boolean NOT"><code>++bu:dejs:format</code></a>
30+
31+### c
32+
33+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#cidejs-softformat' title="Decode json (unit): Maybe transform"><code>++ci:dejs-soft:format</code></a>
34+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#cidejsformat' title="Decode json: Maybe transform"><code>++ci:dejs:format</code></a>
35+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#cudejs-softformat' title="Decode json (unit): Transform"><code>++cu:dejs-soft:format</code></a>
36+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#cudejsformat' title="Decode json: Transform"><code>++cu:dejs:format</code></a>
37+
38+### d
39+
40+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dadejs-softformat' title="Decode json (unit): UTC date"><code>++da:dejs-soft:format</code></a>
41+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dankdejs-softformat' title="Decode json (unit): Tank"><code>++dank:dejs-soft:format</code></a>
42+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dejs-softformat' title="Container arm for unitized JSON decoding reparsers"><code>++dejs-soft:format</code></a>
43+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#dejsformat' title="Container arm for JSON decoding reparsers"><code>++dejs:format</code></a>
44+<a class="tooltip" href='/docs/hoon/reference/zuse/2e_2-3/#de-jsonhtml' title="Parse JSON"><code>++de-json:html</code></a>
45+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#didejs-softformat' title="Decode json (unit): Millisecond date"><code>++di:dejs-soft:format</code></a>
46+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#didejsformat' title="Decode json: Millisecond date"><code>++di:dejs:format</code></a>
47+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#dudejsformat' title="Decode json: Second date"><code>++du:dejs:format</code></a>
48+
49+### e
50+
51+<a class="tooltip" href='/docs/hoon/reference/zuse/2e_2-3/#en-jsonhtml' title="Parse JSON"><code>++en-json:html</code></a>
52+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#enjsformat' title="Container arm for JSON encoders"><code>++enjs:format</code></a>
53+
54+### f
55+
56+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#frondenjsformat' title="Encode json: Object from key-value pair"><code>++frond:enjs:format</code></a>
57+
58+### j
59+
60+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#json-rnformat' title="Json to rn parser"><code>++json-rn:format</code></a>
61+
62+### m
63+
64+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#mudejs-softformat' title="Decode json (unit): True unit"><code>++mu:dejs-soft:format</code></a>
65+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#mudejsformat' title="Decode json: True unit"><code>++mu:dejs:format</code></a>
66+
67+### n
68+
69+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nedejs-softformat' title="Decode json (unit): Number as real"><code>++ne:dejs-soft:format</code></a>
70+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nedejsformat' title="Decode json: Number as real"><code>++ne:dejs:format</code></a>
71+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nidejs-softformat' title="Decode json (unit): Number as integer"><code>++ni:dejs-soft:format</code></a>
72+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nidejsformat' title="Decode json: Number as integer"><code>++ni:dejs:format</code></a>
73+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nodejs-softformat' title="Decode json (unit): Number as knot"><code>++no:dejs-soft:format</code></a>
74+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nodejsformat' title="Decode json: Number as knot"><code>++no:dejs:format</code></a>
75+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nudejsformat' title="Decode json: Parse string as hex"><code>++nu:dejs:format</code></a>
76+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#numbenjsformat' title="Encode json: Number from unsigned"><code>++numb:enjs:format</code></a>
77+
78+### o
79+
80+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#of-wainformat' title="Line list to cord"><code>++of-wain:format</code></a>
81+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#of-wallformat' title="Line list to tape"><code>++of-wall:format</code></a>
82+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ofdejs-softformat' title="Decode json (unit): Object as frond"><code>++of:dejs-soft:format</code></a>
83+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ofdejsformat' title="Decode json: Object as frond"><code>++of:dejs:format</code></a>
84+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ojdejsformat' title="Decode json: Object as jug"><code>++oj:dejs:format</code></a>
85+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#omdejs-softformat' title="Decode json (unit): Object as map"><code>++om:dejs-soft:format</code></a>
86+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#omdejsformat' title="Decode json: Object as map"><code>++om:dejs:format</code></a>
87+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#opdejs-softformat' title="Decode json (unit): Parse keys of map"><code>++op:dejs-soft:format</code></a>
88+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#opdejsformat' title="Decode json: Parse keys of map"><code>++op:dejs:format</code></a>
89+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ot-rawdejs-softformat' title="Decode json (unit): Object as list of units, raw"><code>++ot-raw:dejs-soft:format</code></a>
90+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ot-rawdejsformat' title="Decode json: Object as tuple, raw"><code>++ot-raw:dejs:format</code></a>
91+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#otdejs-softformat' title="Decode json (unit): Object as tuple"><code>++ot:dejs-soft:format</code></a>
92+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#otdejsformat' title="Decode json: Object as tuple"><code>++ot:dejs:format</code></a>
93+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ou-rawdejsformat' title="Decode json: Object of units, raw"><code>++ou-raw:dejs:format</code></a>
94+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#oudejsformat' title="Decode json: Object of units"><code>++ou:dejs:format</code></a>
95+
96+### p
97+
98+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#padejsformat' title="Decode json: String as path"><code>++pa:dejs:format</code></a>
99+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#pairsenjsformat' title="Encode json: Object from key-value pair list"><code>++pairs:enjs:format</code></a>
100+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#pathenjsformat' title="Encode json: String from path"><code>++path:enjs:format</code></a>
101+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#pedejs-softformat' title="Decode json (unit): Prefix"><code>++pe:dejs-soft:format</code></a>
102+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#pedejsformat' title="Decode json: Prefix"><code>++pe:dejs:format</code></a>
103+
104+### r
105+
106+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#redejs-softformat' title="Decode json (unit): Recursive reparser"><code>++re:dejs-soft:format</code></a>
107+
108+### s
109+
110+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sadejs-softformat' title="Decode json (unit): String as tape"><code>++sa:dejs-soft:format</code></a>
111+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sedejsformat' title="Decode json: String as tape"><code>++sa:dejs:format</code></a>
112+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sddejsformat' title="Decode json: String @ud as date"><code>++sd:dejs:format</code></a>
113+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sedejsformat' title="Decode json: String as aura"><code>++se:dejs:format</code></a>
114+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#sectenjsformat' title="Encode json: Seconds timestamp"><code>++sect:enjs:format</code></a>
115+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#shipenjsformat' title="Encode json: String from ship"><code>++ship:enjs:format</code></a>
116+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sodejs-softformat' title="Decode json (unit): String as cord"><code>++so:dejs-soft:format</code></a>
117+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sodejsformat' title="Decode json: String as cord"><code>++so:dejs:format</code></a>
118+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sudejs-softformat' title="Decode json (unit): Parse string"><code>++su:dejs-soft:format</code></a>
119+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sudejsformat' title="Decode json: Parse string"><code>++su:dejs:format</code></a>
120+
121+### t
122+
123+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#tankenjsformat' title="Encode json: Tank as string array"><code>++tank:enjs:format</code></a>
124+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#tapeenjsformat' title="Encode json: String from tape"><code>++tape:enjs:format</code></a>
125+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#timeenjsformat' title="Encode json: Millisecond timestamp"><code>++time:enjs:format</code></a>
126+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#to-wainformat' title="Cord to line list"><code>++to-wain:format</code></a>
127+
128+### u
129+
130+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ufdejsformat' title="Decode json: Unit fall"><code>++uf:dejs:format</code></a>
131+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#uldejs-softformat' title="Decode json (unit): Null"><code>++ul:dejs-soft:format</code></a>
132+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#uldejsformat' title="Decode json: Null"><code>++ul:dejs:format</code></a>
133+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#undejsformat' title="Decode json: Unit need"><code>++un:dejs:format</code></a>
134+
135+### w
136+
137+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#wallenjsformat' title="Encode json: String from wall"><code>++wall:enjs:format</code></a>
138+
139+### z
140+
141+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zadejs-softformat' title="Decode json (unit): Full unit pole"><code>++za:dejs-soft:format</code></a>
142+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zadejsformat' title="Decode json: Full unit pole"><code>++za:dejs:format</code></a>
143+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zldejs-softformat' title="Decode json (unit): Collapse unit list"><code>++zl:dejs-soft:format</code></a>
144+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zldejsformat' title="Decode json: Collapse unit list"><code>++zl:dejs:format</code></a>
145+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zmdejs-softformat' title="Decode json (unit): Collapse unit map"><code>++zm:dejs-soft:format</code></a>
146+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zmdejsformat' title="Decode json: Collapse unit map"><code>++zm:dejs:format</code></a>
147+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zpdejs-softformat' title="Decode json (unit): Unit tuple"><code>++zp:dejs-soft:format</code></a>
148+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zpdejsformat' title="Decode json: Unit tuple"><code>++zp:dejs:format</code></a>
149+
150+## By Section
151+
152+### 2d (1-5): Formatting functions: Line lists and JSON encoding
153+
154+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#to-wainformat' title="Cord to line list"><code>++to-wain:format</code></a>
155+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#of-wainformat' title="Line list to cord"><code>++of-wain:format</code></a>
156+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#of-wallformat' title="Line list to tape"><code>++of-wall:format</code></a>
157+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#json-rnformat' title="Json to rn parser"><code>++json-rn:format</code></a>
158+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#enjsformat' title="Container arm for JSON encoders"><code>++enjs:format</code></a>
159+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#frondenjsformat' title="Encode json: Object from key-value pair"><code>++frond:enjs:format</code></a>
160+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#pairsenjsformat' title="Encode json: Object from key-value pair list"><code>++pairs:enjs:format</code></a>
161+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#tapeenjsformat' title="Encode json: String from tape"><code>++tape:enjs:format</code></a>
162+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#wallenjsformat' title="Encode json: String from wall"><code>++wall:enjs:format</code></a>
163+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#shipenjsformat' title="Encode json: String from ship"><code>++ship:enjs:format</code></a>
164+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#numbenjsformat' title="Encode json: Number from unsigned"><code>++numb:enjs:format</code></a>
165+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#sectenjsformat' title="Encode json: Seconds timestamp"><code>++sect:enjs:format</code></a>
166+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#timeenjsformat' title="Encode json: Millisecond timestamp"><code>++time:enjs:format</code></a>
167+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#pathenjsformat' title="Encode json: String from path"><code>++path:enjs:format</code></a>
168+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_1-5/#tankenjsformat' title="Encode json: Tank as string array"><code>++tank:enjs:format</code></a>
169+
170+### 2d (6): Formatting functions: JSON decoding
171+
172+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#dejsformat' title="Container arm for JSON decoding reparsers"><code>++dejs:format</code></a>
173+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ardejsformat' title="Decode json: Array as list"><code>++ar:dejs:format</code></a>
174+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#asdejsformat' title="Decode json: Array as set"><code>++as:dejs:format</code></a>
175+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#atdejsformat' title="Decode json: Array as tuple"><code>++at:dejs:format</code></a>
176+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#at-rawdejsformat' title="Decode json: Array as tuple, raw"><code>++at-raw:dejs:format</code></a>
177+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#bodejsformat' title="Decode json: Boolean"><code>++bo:dejs:format</code></a>
178+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#budejsformat' title="Decode json: Boolean NOT"><code>++bu:dejs:format</code></a>
179+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#cidejsformat' title="Decode json: Maybe transform"><code>++ci:dejs:format</code></a>
180+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#cudejsformat' title="Decode json: Transform"><code>++cu:dejs:format</code></a>
181+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#didejsformat' title="Decode json: Millisecond date"><code>++di:dejs:format</code></a>
182+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#dudejsformat' title="Decode json: Second date"><code>++du:dejs:format</code></a>
183+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#mudejsformat' title="Decode json: True unit"><code>++mu:dejs:format</code></a>
184+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nedejsformat' title="Decode json: Number as real"><code>++ne:dejs:format</code></a>
185+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nidejsformat' title="Decode json: Number as integer"><code>++ni:dejs:format</code></a>
186+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nodejsformat' title="Decode json: Number as knot"><code>++no:dejs:format</code></a>
187+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#nudejsformat' title="Decode json: Parse string as hex"><code>++nu:dejs:format</code></a>
188+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ofdejsformat' title="Decode json: Object as frond"><code>++of:dejs:format</code></a>
189+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#otdejsformat' title="Decode json: Object as tuple"><code>++ot:dejs:format</code></a>
190+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ot-rawdejsformat' title="Decode json: Object as tuple, raw"><code>++ot-raw:dejs:format</code></a>
191+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#oudejsformat' title="Decode json: Object of units"><code>++ou:dejs:format</code></a>
192+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ou-rawdejsformat' title="Decode json: Object of units, raw"><code>++ou-raw:dejs:format</code></a>
193+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ojdejsformat' title="Decode json: Object as jug"><code>++oj:dejs:format</code></a>
194+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#omdejsformat' title="Decode json: Object as map"><code>++om:dejs:format</code></a>
195+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#opdejsformat' title="Decode json: Parse keys of map"><code>++op:dejs:format</code></a>
196+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#padejsformat' title="Decode json: String as path"><code>++pa:dejs:format</code></a>
197+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#pedejsformat' title="Decode json: Prefix"><code>++pe:dejs:format</code></a>
198+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sedejsformat' title="Decode json: String as tape"><code>++sa:dejs:format</code></a>
199+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sddejsformat' title="Decode json: String @ud as date"><code>++sd:dejs:format</code></a>
200+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sedejsformat' title="Decode json: String as aura"><code>++se:dejs:format</code></a>
201+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sodejsformat' title="Decode json: String as cord"><code>++so:dejs:format</code></a>
202+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#sudejsformat' title="Decode json: Parse string"><code>++su:dejs:format</code></a>
203+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#ufdejsformat' title="Decode json: Unit fall"><code>++uf:dejs:format</code></a>
204+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#undejsformat' title="Decode json: Unit need"><code>++un:dejs:format</code></a>
205+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#uldejsformat' title="Decode json: Null"><code>++ul:dejs:format</code></a>
206+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zadejsformat' title="Decode json: Full unit pole"><code>++za:dejs:format</code></a>
207+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zldejsformat' title="Decode json: Collapse unit list"><code>++zl:dejs:format</code></a>
208+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zpdejsformat' title="Decode json: Unit tuple"><code>++zp:dejs:format</code></a>
209+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_6/#zmdejsformat' title="Decode json: Collapse unit map"><code>++zm:dejs:format</code></a>
210+
211+### 2d (7): Formatting functions: JSON decoding (unit)
212+
213+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dejs-softformat' title="Container arm for unitized JSON decoding reparsers"><code>++dejs-soft:format</code></a>
214+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ardejs-softformat' title="Decode json (unit): Array as list"><code>++ar:dejs-soft:format</code></a>
215+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#atdejs-softformat' title="Decode json (unit): Array as tuple"><code>++at:dejs-soft:format</code></a>
216+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#at-rawdejs-softformat' title="Decode json (unit): Array as tuple, raw"><code>++at-raw:dejs-soft:format</code></a>
217+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#bodejs-softformat' title="Decode json (unit): Boolean"><code>++bo:dejs-soft:format</code></a>
218+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#budejs-softformat' title="Decode json (unit): Boolean NOT"><code>++bu:dejs-soft:format</code></a>
219+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#cidejs-softformat' title="Decode json (unit): Maybe transform"><code>++ci:dejs-soft:format</code></a>
220+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#cudejs-softformat' title="Decode json (unit): Transform"><code>++cu:dejs-soft:format</code></a>
221+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dadejs-softformat' title="Decode json (unit): UTC date"><code>++da:dejs-soft:format</code></a>
222+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#dankdejs-softformat' title="Decode json (unit): Tank"><code>++dank:dejs-soft:format</code></a>
223+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#didejs-softformat' title="Decode json (unit): Millisecond date"><code>++di:dejs-soft:format</code></a>
224+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#mudejs-softformat' title="Decode json (unit): True unit"><code>++mu:dejs-soft:format</code></a>
225+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nedejs-softformat' title="Decode json (unit): Number as real"><code>++ne:dejs-soft:format</code></a>
226+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nidejs-softformat' title="Decode json (unit): Number as integer"><code>++ni:dejs-soft:format</code></a>
227+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#nodejs-softformat' title="Decode json (unit): Number as knot"><code>++no:dejs-soft:format</code></a>
228+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ofdejs-softformat' title="Decode json (unit): Object as frond"><code>++of:dejs-soft:format</code></a>
229+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#otdejs-softformat' title="Decode json (unit): Object as tuple"><code>++ot:dejs-soft:format</code></a>
230+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#ot-rawdejs-softformat' title="Decode json (unit): Object as list of units, raw"><code>++ot-raw:dejs-soft:format</code></a>
231+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#omdejs-softformat' title="Decode json (unit): Object as map"><code>++om:dejs-soft:format</code></a>
232+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#opdejs-softformat' title="Decode json (unit): Parse keys of map"><code>++op:dejs-soft:format</code></a>
233+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#pedejs-softformat' title="Decode json (unit): Prefix"><code>++pe:dejs-soft:format</code></a>
234+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#redejs-softformat' title="Decode json (unit): Recursive reparser"><code>++re:dejs-soft:format</code></a>
235+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sadejs-softformat' title="Decode json (unit): String as tape"><code>++sa:dejs-soft:format</code></a>
236+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sodejs-softformat' title="Decode json (unit): String as cord"><code>++so:dejs-soft:format</code></a>
237+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#sudejs-softformat' title="Decode json (unit): Parse string"><code>++su:dejs-soft:format</code></a>
238+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#uldejs-softformat' title="Decode json (unit): Null"><code>++ul:dejs-soft:format</code></a>
239+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zadejs-softformat' title="Decode json (unit): Full unit pole"><code>++za:dejs-soft:format</code></a>
240+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zldejs-softformat' title="Decode json (unit): Collapse unit list"><code>++zl:dejs-soft:format</code></a>
241+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zpdejs-softformat' title="Decode json (unit): Unit tuple"><code>++zp:dejs-soft:format</code></a>
242+<a class="tooltip" href='/docs/hoon/reference/zuse/2d_7/#zmdejs-softformat' title="Decode json (unit): Collapse unit map"><code>++zm:dejs-soft:format</code></a>
243+
244+### 2e (2-3): Web text: JSON printing and parsing
245+
246+<a class="tooltip" href='/docs/hoon/reference/zuse/2e_2-3/#en-jsonhtml' title="Parse JSON"><code>++en-json:html</code></a>
247+<a class="tooltip" href='/docs/hoon/reference/zuse/2e_2-3/#de-jsonhtml' title="Parse JSON"><code>++de-json:html</code></a>
content/getting-started/_index.md+9
@@ -77,3 +77,12 @@ Or to install `snap` for your distribution, snapcraft provides [installation ins
7777</style>
7878
7979If you'd like to have more direct control over the Urbit virtual machine, or are setting up Urbit on a cloud droplet, try [installation using the command line](/getting-started/cli).
80+
81+### Next steps
82+
83+If you haven't already done so, we recommend spending 10 minutes or so reading
84+[Understanding Urbit](/understanding-urbit) to get acquainted with the project.
85+Then once you've been become acquainted with your ship and explored the network
86+for awhile, consider checking out the [User's Manual](/using) which provides
87+guidance and reference material for operating your ship, as well as explanations
88+for Urbit concepts everyone should eventually learn.
content/getting-started/planet.md+1−1
@@ -11,7 +11,7 @@ A planet is a permanent Urbit identity. Like all Urbit identities, they can neve
1111There are a few ways to get your own planet:
1212
1313- Getting an invitation from a friend (or stranger).
14−- Purchasing a planet, including hosting, from a [hosting provider](#hosting-providers) such as [geturbitid.com](https://www.geturbitid.com/).
14+- Purchasing a planet, including hosting, from a [hosting provider](#hosting-providers).
1515- Manually setting up and hosting a planet purchased from a third party such as [urbit.live](https://urbit.live), [OpenSea](https://opensea.io), [planet.market](https://planet.market/), [urbit.me](https://urbit.me), [urth systems](https://urth.systems/), or [Urbit Marketplace](https://urbitmarketplace.com/).
1616
1717Note that when you buy a planet, you should ensure with the provider that your parent star is operating. If you need to escape a non-operational star, see [Escaping A Sponsor](/using/id/using-bridge#escaping-your-sponsor).
content/grants/cypherscope-bot.mdnew file+80
@@ -0,0 +1,80 @@
1++++
2+title = "Cypherscope Bot"
3+date = "2021-09-13"
4+[taxonomies]
5+grant_type = ["Proposal"]
6+grant_category = ["App Dev: Other"]
7+[extra]
8+image = ""
9+description = "On-demand financial charts chat bot"
10+reward = 2
11+assignee = "~mitten-dapper, ~ristyc-ridwyx"
12+grant_id = "P0068"
13+completed = false
14+canceled = false
15+link = ""
16++++
17+
18+## Cyperscope Bot - an on-demand financial charts chat bot
19+
20+Urbit chat bot that provides on-demand financial charts based on [this bot](https://www.alphabotsystem.com/guide/charting)
21+
22+We expect to have a Ship or a Moon for our bot that answers incoming commands by replying with a chart image queried from the TradingView API.
23+
24+## User flow
25+
26+- User queries our bot by typing a command into chat like “chart btcusd 1h”.
27+
28+ -- Command parameters include ticker, timeframe (optional), candle type (optional), indicators (optional).
29+ -- We’ll attempt to match AlphaBot’s available parameters (at the bottom of [this page](https://www.alphabotsystem.com/guide/charting).
30+ -- More command parameters will potentially be added based on time constraints and feasibility.
31+
32+- Chatbot framework relays message to our bot (Cypherscope ship).
33+
34+ -- [Chatbot framework](https://github.com/robkorn/urbit-chatbot-framework)
35+
36+ -- Our bot is ideally a chat participant.
37+
38+ -- If our bot does not understand the command, return a helpful error message.
39+
40+- Bot parses the command and queries TradingView API for a chart.
41+
42+- Bot sends a message in chat with the chart image.
43+
44+ -- The images may be hosted on our ship. This part is a little unclear as of now.
45+
46+ -- The chart should have a consistent and unobtrusive size every time. TradingView API might already handle this.
47+
48+ -- Users should be able to delete the chart from the chat to avoid disrupting the flow of conversation.
49+
50+## Risks
51+
52+For transparency we have the following open questions and will dive deeper to resolve them:
53+
54+- Where are images hosted and for what time period?
55+
56+- How should the hardware running the ship be paid for?
57+
58+ -- If this project catches on we could add a paid tier with more features, accepting payment in crypto to our bot’s ship.
59+
60+- How should the TradingView chart API be paid for?
61+
62+## Milestones
63+
64+Milestone 1: Bot prototype + Moon deployment
65+
66+Estimated completion: 2 week
67+
68+Payment: 1 star
69+
70+Create chatbot that responds to incoming messages in the format of "c {ticker} {time interval}" and return a chart image with relevant financial data. The bot should fetch data for any asset supported by TradingView API, such as stocks, crypto, forex, or metals. Deploy this prototype bot to a Moon.
71+
72+Modify the chatbot framework we're using so that our Moon reacts when it is added to a new chat. When added, the bot displays a welcome message + menu. Add "c help" command for a full list of the bot's features. Ensure improper inputs like "c nonexistentTicker" returns a helpful error message.
73+
74+### Milestone 2: Accept payments
75+
76+Estimated completion: 2 weeks
77+
78+Payment: 1 star
79+
80+Allow bot to accept payment to the Moon it is hosted on to pay for upgraded features. Create chat interface so users of our bot can upgrade or downgrade seamlessly.
content/grants/network-explorer-data-pipeline-http-api.md+2−2
@@ -10,10 +10,10 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Build a public, open HTTP API for exploring metrics about the Urbit network."
1212reward = 5
13−assignee = "Christopher King"
13+assignee = "~dinleb-rambep"
1414id = "1101665172"
1515completed = false
16−canceled = true
16+canceled = false
1717link = ""
1818+++
1919
content/grants/overhaul-the-urbitorg-website.md+2−2
@@ -9,10 +9,10 @@ grant_category = [ "Design" ]
99[extra]
1010image = ""
1111description = "Rework urbit.org to encourage participation with the project."
12−reward = 6
12+reward = 2
1313assignee = "~radbur-sivmus"
1414id = "246698762"
15−completed = false
15+completed = true
1616canceled = false
1717link = ""
1818+++
content/grants/static-site-generation.md+7−29
@@ -41,44 +41,22 @@ The third common use case we will build is rendering a listing of all blog posts
41414. He then clicks “Serve Page”, and his Publish Notebook is now rendered into static HTML and served at /justinblog.
42425. He then goes to the Groups app and finds his Justin Blog. He writes a new article, and publishes it, then edits one of his existing articles and publishes it. He sees the latest state reflected on his new static site.
4343
44−## Milestones
45−
46−Milestone 1 - Gall agent developed
47−
48−Estimated completion:
49−
50−Payment: 3 stars
51−
52−Build agent that has the build pipelines specified and watches for graph-store updates.
53−
54−Milestone 2 - HTML Template Examples
55−
56−Estimated completion:
57−
58−Payment: 1 star
59−
60−Build out the two rich HTML templates for Publish notebook data specified above in “use cases”
61−
62−Milestone 3 - Grid Tile Development
63−
64−Estimated completion:
65−
66−Payment: 1 star
67−
68−Build out a tile in Grid for managing these web blogs.
69−
70−Architecture:
71−One Gall agent: %static-blog
44+### Architecture: One Gall agent - %static-blog
7245
7346++on-init: On initial load, tells file-server that it wants to serve a webpage at /static-blog, and subscribes to /updates on %graph-store
47+
7448++on-load: n/a
49+
7550++on-poke: Receives pokes which allow one to A) associate a particular graph with a particular mark that will convert that graph to a static webpage, B) dissociate them once associated, C) serve a set of static webpages at a path to the public web, D) stop serving a set of static webpages at a path.
51+
7652++on-watch: Subscribe to the state of the application
53+
7754++on-peek: Read out the files of a particular static site, read out the set of associations
7855
79−Future Directions:
56+### Future Directions:
8057
8158- More marks can be built out that wrap the Sail generated from the graph-store -> html conversion and inject calls-to-action, payment links, and other forms of plugin content using Ford marks as a build pipeline
59+
8260- Other graph types can and should eventually be able to converted to static sites as well.
8361
8462## Milestones
content/grants/urbian-a-customized-linux-distribution-for-urbit-appliances.md+1−1
@@ -13,7 +13,7 @@ reward = 2
1313assignee = "~botter-nidnul"
1414id = "337545546"
1515completed = false
16−canceled = false
16+canceled = true
1717link = ""
1818+++
1919
content/grants/urbit-event-series.md+1−1
@@ -12,7 +12,7 @@ description = "A series of community-focused events to create a new knowledge ba
1212reward = 6
1313assignee = "~naplet-hildec"
1414id = "1751024973"
15−completed = false
15+completed = true
1616canceled = false
1717link = ""
1818+++
content/using/_index.md+3−3
@@ -1,17 +1,17 @@
11+++
2−title = "Usage Docs"
2+title = "User's Manual"
33sort_by = "weight"
44template = "sections/docs/chapters.html"
55+++
66
7−Welcome to the usage documentation for the Urbit project. This documentation is
7+Welcome to the User's Manual for the Urbit project. This documentation is
88maintained by [Tlon](https://tlon.io) and the Urbit community in a public
99[Github repository](https://github.com/urbit/urbit.org). Issues and
1010contributions are welcome.
1111
1212This documentation provides a series of guides and reference material for
1313assisting you in the usage and operations of your ship. If you're looking for
14−documentation on how to *develop* on Urbit, see our [development docs](/docs/).
14+documentation on how to _develop_ on Urbit, see our [development docs](/docs/).
1515
1616### [Urbit OS](/using/os/)
1717
content/using/os/_index.md+1−1
@@ -10,7 +10,7 @@ This section describes how to interact with your running Urbit ship: this
1010includes working with the filesystem, command line (`dojo`), resolving common
1111issues, and more.
1212
13−### [Getting Started](/using/os/getting-started)
13+### [Basics](/using/os/basics)
1414
1515An overview of common commands and useful general knowledge for operating your
1616ship.
content/using/os/getting-started.md → content/using/os/basics.mdrenamed+1−1
@@ -1,5 +1,5 @@
11+++
2−title = "Getting Started"
2+title = "Basics"
33description = "How to operate your ship, including using your ship's filesystem and messaging applications, starting a moon, or requesting a DNS entry."
44template = "doc.html"
55weight = 1
content/using/os/dist-faq.md+76−3
@@ -4,7 +4,7 @@ template = "doc.html"
44weight = 9
55+++
66
7−This document concerns the September 2021 release of the software distribution OTA, codenamed "Grid." It is current as of 2021-09-30 at 01:03 AM EST.
7+This document concerns the September 2021 release of the software distribution OTA, codenamed "Grid." It is current as of 2021-10-01 at 05:52 AM EST.
88
99## Changes
1010
@@ -34,12 +34,14 @@ The table lists the suffixes (last 5 characters) of the %cz hashes.
3434
3535| Software | Desk | %cz Hash |
3636| ------------ | ---------- | --------- |
37−| Arvo/OS | %base | `36cdn` |
37+| Arvo/OS | %base | `krdh3` |
3838| Home Screen | %garden | `7ai82` |
39−| Groups | %landscape | `e4jfn` |
39+| Groups | %landscape | `m1nt8` |
4040| BTC Wallet | %bitcoin | `8kkfo` |
4141| Web Terminal | %webterm | `b2pme` |
4242
43+
44+
4345Run `+trouble` to see these hashes.
4446
4547**How do I see the base hashes for my ship?**
@@ -79,6 +81,18 @@ Ships with the OTA will not be able to communicate over graph store with ships w
7981
8082See above. Once your peers receive the OTA, you will be able to communicate again.
8183
84+Your sponsor or your sponsor's sponsor also might have only gotten the first OTA
85+but not the latest one, if either of them are not Tlon stars/galaxies. Try
86+installing from one of Tlon's stars with
87+
88+```
89+|install ~litzod %kids, =local %base
90+|install ~litzod %garden
91+|install ~litzod %landscape
92+|install ~litzod %webterm
93+|install ~litzod %bitcoin
94+```
95+
8296**Can I still `|hi` between pre and post OTA ships?**
8397
8498`|hi` will continue to work between pre and post OTA ships.
@@ -87,3 +101,62 @@ See above. Once your peers receive the OTA, you will be able to communicate agai
87101
88102`|ota` will continue to work on ships without the OTA, even if their OTA provider is running the OTA.
89103After the OTA, the `|ota` command is removed and is replaced by the `|install` command.
104+
105+**The OTA failed for me with `%error-validating`.**
106+
107+Tlon is aware of [this issue](https://github.com/urbit/urbit/issues/5271) and is working on a fix.
108+
109+The error will print near the bottom of the output from the failed OTA, and will be similar to:
110+
111+```
112+[ %error-validating
113+ /backup/ship/~littel-wolfur/vim/~2020.12.11..06.50.27..c12d/graph-update
114+]
115+[ %validate-page-fail
116+ /backup/ship/~littel-wolfur/vim/~2020.12.11..06.50.27..c12d/graph-update
117+ %from
118+ %graph-update
119+]
120+```
121+
122+This is caused by some leftover backup files from a previous migration for which Clay no longer has marks.
123+
124+As a workaround: you can remove these files and retry the OTA:
125+
126+dojo:
127+
128+```
129+|unmount %home
130+|mount /=home=
131+```
132+
133+bash:
134+
135+```bash
136+rm -r your-ship/home/backup
137+```
138+
139+dojo:
140+
141+```
142+|commit %home
143+|ota (sein:title our now our) %kids
144+```
145+
146+**The OTA failed for me with `%mate-conflict`**
147+
148+You can instruct Clay to simply override the contents of the relevant files with the version from your sponsor:
149+
150+dojo:
151+
152+```
153+|merge %home (sein:title our now our) %kids, =gem %take-that
154+```
155+
156+This will start the upgrade. Note that on a galaxy, star, or planet, you should also run
157+
158+```
159+|merge %kids (sein:title our now our) %kids, =gem %only-that
160+```
161+
162+to make sure OTAs go out to your sponsored ships (stars, planets, or moons).
lib/glossary.js+596
@@ -6526,4 +6526,600 @@ export const glossary = [
65266526 slug: "https://urbit.org/docs/reference/library/3f/#zyrtun",
65276527 desc: "Used in the Hoon standard library.",
65286528 },
6529+ // zuse
6530+ {
6531+ name: "Decode json (unit): Array as list",
6532+ symbol: "ar:dejs-soft:format",
6533+ usage: "zuse",
6534+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#ardejs-softformat",
6535+ desc: "Used in the Zuse library.",
6536+ },
6537+ {
6538+ name: "Decode json: Array as list",
6539+ symbol: "ar:dejs:format",
6540+ usage: "zuse",
6541+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ardejsformat",
6542+ desc: "Used in the Zuse library.",
6543+ },
6544+ {
6545+ name: "Decode json: Array as set",
6546+ symbol: "as:dejs:format",
6547+ usage: "zuse",
6548+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#asdejsformat",
6549+ desc: "Used in the Zuse library.",
6550+ },
6551+ {
6552+ name: "Decode json (unit): Array as tuple, raw",
6553+ symbol: "at-raw:dejs-soft:format",
6554+ usage: "zuse",
6555+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#at-rawdejs-softformat",
6556+ desc: "Used in the Zuse library.",
6557+ },
6558+ {
6559+ name: "Decode json: Array as tuple, raw",
6560+ symbol: "at-raw:dejs:format",
6561+ usage: "zuse",
6562+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#at-rawdejsformat",
6563+ desc: "Used in the Zuse library.",
6564+ },
6565+ {
6566+ name: "Decode json (unit): Array as tuple",
6567+ symbol: "at:dejs-soft:format",
6568+ usage: "zuse",
6569+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#atdejs-softformat",
6570+ desc: "Used in the Zuse library.",
6571+ },
6572+ {
6573+ name: "Decode json: Array as tuple",
6574+ symbol: "at:dejs:format",
6575+ usage: "zuse",
6576+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#atdejsformat",
6577+ desc: "Used in the Zuse library.",
6578+ },
6579+ {
6580+ name: "Decode json (unit): Boolean",
6581+ symbol: "bo:dejs-soft:format",
6582+ usage: "zuse",
6583+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#bodejs-softformat",
6584+ desc: "Used in the Zuse library.",
6585+ },
6586+ {
6587+ name: "Decode json: Boolean",
6588+ symbol: "bo:dejs:format",
6589+ usage: "zuse",
6590+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#bodejsformat",
6591+ desc: "Used in the Zuse library.",
6592+ },
6593+ {
6594+ name: "Decode json (unit): Boolean NOT",
6595+ symbol: "bu:dejs-soft:format",
6596+ usage: "zuse",
6597+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#budejs-softformat",
6598+ desc: "Used in the Zuse library.",
6599+ },
6600+ {
6601+ name: "Decode json: Boolean NOT",
6602+ symbol: "bu:dejs:format",
6603+ usage: "zuse",
6604+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#budejsformat",
6605+ desc: "Used in the Zuse library.",
6606+ },
6607+ {
6608+ name: "Decode json (unit): Maybe transform",
6609+ symbol: "ci:dejs-soft:format",
6610+ usage: "zuse",
6611+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#cidejs-softformat",
6612+ desc: "Used in the Zuse library.",
6613+ },
6614+ {
6615+ name: "Decode json: Maybe transform",
6616+ symbol: "ci:dejs:format",
6617+ usage: "zuse",
6618+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#cidejsformat",
6619+ desc: "Used in the Zuse library.",
6620+ },
6621+ {
6622+ name: "Decode json (unit): Transform",
6623+ symbol: "cu:dejs-soft:format",
6624+ usage: "zuse",
6625+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#cudejs-softformat",
6626+ desc: "Used in the Zuse library.",
6627+ },
6628+ {
6629+ name: "Decode json: Transform",
6630+ symbol: "cu:dejs:format",
6631+ usage: "zuse",
6632+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#cudejsformat",
6633+ desc: "Used in the Zuse library.",
6634+ },
6635+ {
6636+ name: "Decode json (unit): UTC date",
6637+ symbol: "da:dejs-soft:format",
6638+ usage: "zuse",
6639+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#dadejs-softformat",
6640+ desc: "Used in the Zuse library.",
6641+ },
6642+ {
6643+ name: "Decode json (unit): Tank",
6644+ symbol: "dank:dejs-soft:format",
6645+ usage: "zuse",
6646+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#dankdejs-softformat",
6647+ desc: "Used in the Zuse library.",
6648+ },
6649+ {
6650+ name: "Container arm for unitized JSON decoding reparsers",
6651+ symbol: "dejs-soft:format",
6652+ usage: "zuse",
6653+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#dejs-softformat",
6654+ desc: "Used in the Zuse library.",
6655+ },
6656+ {
6657+ name: "Container arm for JSON decoding reparsers",
6658+ symbol: "dejs:format",
6659+ usage: "zuse",
6660+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#dejsformat",
6661+ desc: "Used in the Zuse library.",
6662+ },
6663+ {
6664+ name: "Parse JSON",
6665+ symbol: "de-json:html",
6666+ usage: "zuse",
6667+ slug: "https://urbit.org/docs/hoon/reference/zuse/2e_2-3/#de-jsonhtml",
6668+ desc: "Used in the Zuse library.",
6669+ },
6670+ {
6671+ name: "Decode json (unit): Millisecond date",
6672+ symbol: "di:dejs-soft:format",
6673+ usage: "zuse",
6674+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#didejs-softformat",
6675+ desc: "Used in the Zuse library.",
6676+ },
6677+ {
6678+ name: "Decode json: Millisecond date",
6679+ symbol: "di:dejs:format",
6680+ usage: "zuse",
6681+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#didejsformat",
6682+ desc: "Used in the Zuse library.",
6683+ },
6684+ {
6685+ name: "Decode json: Second date",
6686+ symbol: "du:dejs:format",
6687+ usage: "zuse",
6688+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#dudejsformat",
6689+ desc: "Used in the Zuse library.",
6690+ },
6691+ {
6692+ name: "Parse JSON",
6693+ symbol: "en-json:html",
6694+ usage: "zuse",
6695+ slug: "https://urbit.org/docs/hoon/reference/zuse/2e_2-3/#en-jsonhtml",
6696+ desc: "Used in the Zuse library.",
6697+ },
6698+ {
6699+ name: "Container arm for JSON encoders",
6700+ symbol: "enjs:format",
6701+ usage: "zuse",
6702+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#enjsformat",
6703+ desc: "Used in the Zuse library.",
6704+ },
6705+ {
6706+ name: "Encode json: Object from key-value pair",
6707+ symbol: "frond:enjs:format",
6708+ usage: "zuse",
6709+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#frondenjsformat",
6710+ desc: "Used in the Zuse library.",
6711+ },
6712+ {
6713+ name: "Json to rn parser",
6714+ symbol: "json-rn:format",
6715+ usage: "zuse",
6716+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#json-rnformat",
6717+ desc: "Used in the Zuse library.",
6718+ },
6719+ {
6720+ name: "Decode json (unit): True unit",
6721+ symbol: "mu:dejs-soft:format",
6722+ usage: "zuse",
6723+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#mudejs-softformat",
6724+ desc: "Used in the Zuse library.",
6725+ },
6726+ {
6727+ name: "Decode json: True unit",
6728+ symbol: "mu:dejs:format",
6729+ usage: "zuse",
6730+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#mudejsformat",
6731+ desc: "Used in the Zuse library.",
6732+ },
6733+ {
6734+ name: "Decode json (unit): Number as real",
6735+ symbol: "ne:dejs-soft:format",
6736+ usage: "zuse",
6737+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#nedejs-softformat",
6738+ desc: "Used in the Zuse library.",
6739+ },
6740+ {
6741+ name: "Decode json: Number as real",
6742+ symbol: "ne:dejs:format",
6743+ usage: "zuse",
6744+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#nedejsformat",
6745+ desc: "Used in the Zuse library.",
6746+ },
6747+ {
6748+ name: "Decode json (unit): Number as integer",
6749+ symbol: "ni:dejs-soft:format",
6750+ usage: "zuse",
6751+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#nidejs-softformat",
6752+ desc: "Used in the Zuse library.",
6753+ },
6754+ {
6755+ name: "Decode json: Number as integer",
6756+ symbol: "ni:dejs:format",
6757+ usage: "zuse",
6758+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#nidejsformat",
6759+ desc: "Used in the Zuse library.",
6760+ },
6761+ {
6762+ name: "Decode json (unit): Number as knot",
6763+ symbol: "no:dejs-soft:format",
6764+ usage: "zuse",
6765+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#nodejs-softformat",
6766+ desc: "Used in the Zuse library.",
6767+ },
6768+ {
6769+ name: "Decode json: Number as knot",
6770+ symbol: "no:dejs:format",
6771+ usage: "zuse",
6772+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#nodejsformat",
6773+ desc: "Used in the Zuse library.",
6774+ },
6775+ {
6776+ name: "Decode json: Parse string as hex",
6777+ symbol: "nu:dejs:format",
6778+ usage: "zuse",
6779+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#nudejsformat",
6780+ desc: "Used in the Zuse library.",
6781+ },
6782+ {
6783+ name: "Encode json: Number from unsigned",
6784+ symbol: "numb:enjs:format",
6785+ usage: "zuse",
6786+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#numbenjsformat",
6787+ desc: "Used in the Zuse library.",
6788+ },
6789+ {
6790+ name: "Line list to cord",
6791+ symbol: "of-wain:format",
6792+ usage: "zuse",
6793+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#of-wainformat",
6794+ desc: "Used in the Zuse library.",
6795+ },
6796+ {
6797+ name: "Line list to tape",
6798+ symbol: "of-wall:format",
6799+ usage: "zuse",
6800+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#of-wallformat",
6801+ desc: "Used in the Zuse library.",
6802+ },
6803+ {
6804+ name: "Decode json (unit): Object as frond",
6805+ symbol: "of:dejs-soft:format",
6806+ usage: "zuse",
6807+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#ofdejs-softformat",
6808+ desc: "Used in the Zuse library.",
6809+ },
6810+ {
6811+ name: "Decode json: Object as frond",
6812+ symbol: "of:dejs:format",
6813+ usage: "zuse",
6814+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ofdejsformat",
6815+ desc: "Used in the Zuse library.",
6816+ },
6817+ {
6818+ name: "Decode json: Object as jug",
6819+ symbol: "oj:dejs:format",
6820+ usage: "zuse",
6821+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ojdejsformat",
6822+ desc: "Used in the Zuse library.",
6823+ },
6824+ {
6825+ name: "Decode json (unit): Object as map",
6826+ symbol: "om:dejs-soft:format",
6827+ usage: "zuse",
6828+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#omdejs-softformat",
6829+ desc: "Used in the Zuse library.",
6830+ },
6831+ {
6832+ name: "Decode json: Object as map",
6833+ symbol: "om:dejs:format",
6834+ usage: "zuse",
6835+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#omdejsformat",
6836+ desc: "Used in the Zuse library.",
6837+ },
6838+ {
6839+ name: "Decode json (unit): Parse keys of map",
6840+ symbol: "op:dejs-soft:format",
6841+ usage: "zuse",
6842+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#opdejs-softformat",
6843+ desc: "Used in the Zuse library.",
6844+ },
6845+ {
6846+ name: "Decode json: Parse keys of map",
6847+ symbol: "op:dejs:format",
6848+ usage: "zuse",
6849+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#opdejsformat",
6850+ desc: "Used in the Zuse library.",
6851+ },
6852+ {
6853+ name: "Decode json (unit): Object as list of units, raw",
6854+ symbol: "ot-raw:dejs-soft:format",
6855+ usage: "zuse",
6856+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#ot-rawdejs-softformat",
6857+ desc: "Used in the Zuse library.",
6858+ },
6859+ {
6860+ name: "Decode json: Object as tuple, raw",
6861+ symbol: "ot-raw:dejs:format",
6862+ usage: "zuse",
6863+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ot-rawdejsformat",
6864+ desc: "Used in the Zuse library.",
6865+ },
6866+ {
6867+ name: "Decode json (unit): Object as tuple",
6868+ symbol: "ot:dejs-soft:format",
6869+ usage: "zuse",
6870+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#otdejs-softformat",
6871+ desc: "Used in the Zuse library.",
6872+ },
6873+ {
6874+ name: "Decode json: Object as tuple",
6875+ symbol: "ot:dejs:format",
6876+ usage: "zuse",
6877+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#otdejsformat",
6878+ desc: "Used in the Zuse library.",
6879+ },
6880+ {
6881+ name: "Decode json: Object of units, raw",
6882+ symbol: "ou-raw:dejs:format",
6883+ usage: "zuse",
6884+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ou-rawdejsformat",
6885+ desc: "Used in the Zuse library.",
6886+ },
6887+ {
6888+ name: "Decode json: Object of units",
6889+ symbol: "ou:dejs:format",
6890+ usage: "zuse",
6891+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#oudejsformat",
6892+ desc: "Used in the Zuse library.",
6893+ },
6894+ {
6895+ name: "Decode json: String as path",
6896+ symbol: "pa:dejs:format",
6897+ usage: "zuse",
6898+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#padejsformat",
6899+ desc: "Used in the Zuse library.",
6900+ },
6901+ {
6902+ name: "Encode json: Object from key-value pair list",
6903+ symbol: "pairs:enjs:format",
6904+ usage: "zuse",
6905+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#pairsenjsformat",
6906+ desc: "Used in the Zuse library.",
6907+ },
6908+ {
6909+ name: "Encode json: String from path",
6910+ symbol: "path:enjs:format",
6911+ usage: "zuse",
6912+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#pathenjsformat",
6913+ desc: "Used in the Zuse library.",
6914+ },
6915+ {
6916+ name: "Decode json (unit): Prefix",
6917+ symbol: "pe:dejs-soft:format",
6918+ usage: "zuse",
6919+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#pedejs-softformat",
6920+ desc: "Used in the Zuse library.",
6921+ },
6922+ {
6923+ name: "Decode json: Prefix",
6924+ symbol: "pe:dejs:format",
6925+ usage: "zuse",
6926+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#pedejsformat",
6927+ desc: "Used in the Zuse library.",
6928+ },
6929+ {
6930+ name: "Decode json (unit): Recursive reparser",
6931+ symbol: "re:dejs-soft:format",
6932+ usage: "zuse",
6933+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#redejs-softformat",
6934+ desc: "Used in the Zuse library.",
6935+ },
6936+ {
6937+ name: "Decode json (unit): String as tape",
6938+ symbol: "sa:dejs-soft:format",
6939+ usage: "zuse",
6940+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#sadejs-softformat",
6941+ desc: "Used in the Zuse library.",
6942+ },
6943+ {
6944+ name: "Decode json: String as tape",
6945+ symbol: "sa:dejs:format",
6946+ usage: "zuse",
6947+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#sedejsformat",
6948+ desc: "Used in the Zuse library.",
6949+ },
6950+ {
6951+ name: "Decode json: String @ud as date",
6952+ symbol: "sd:dejs:format",
6953+ usage: "zuse",
6954+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#sddejsformat",
6955+ desc: "Used in the Zuse library.",
6956+ },
6957+ {
6958+ name: "Decode json: String as aura",
6959+ symbol: "se:dejs:format",
6960+ usage: "zuse",
6961+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#sedejsformat",
6962+ desc: "Used in the Zuse library.",
6963+ },
6964+ {
6965+ name: "Encode json: Seconds timestamp",
6966+ symbol: "sect:enjs:format",
6967+ usage: "zuse",
6968+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#sectenjsformat",
6969+ desc: "Used in the Zuse library.",
6970+ },
6971+ {
6972+ name: "Encode json: String from ship",
6973+ symbol: "ship:enjs:format",
6974+ usage: "zuse",
6975+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#shipenjsformat",
6976+ desc: "Used in the Zuse library.",
6977+ },
6978+ {
6979+ name: "Decode json (unit): String as cord",
6980+ symbol: "so:dejs-soft:format",
6981+ usage: "zuse",
6982+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#sodejs-softformat",
6983+ desc: "Used in the Zuse library.",
6984+ },
6985+ {
6986+ name: "Decode json: String as cord",
6987+ symbol: "so:dejs:format",
6988+ usage: "zuse",
6989+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#sodejsformat",
6990+ desc: "Used in the Zuse library.",
6991+ },
6992+ {
6993+ name: "Decode json (unit): Parse string",
6994+ symbol: "su:dejs-soft:format",
6995+ usage: "zuse",
6996+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#sudejs-softformat",
6997+ desc: "Used in the Zuse library.",
6998+ },
6999+ {
7000+ name: "Decode json: Parse string",
7001+ symbol: "su:dejs:format",
7002+ usage: "zuse",
7003+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#sudejsformat",
7004+ desc: "Used in the Zuse library.",
7005+ },
7006+ {
7007+ name: "Encode json: Tank as string array",
7008+ symbol: "tank:enjs:format",
7009+ usage: "zuse",
7010+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#tankenjsformat",
7011+ desc: "Used in the Zuse library.",
7012+ },
7013+ {
7014+ name: "Encode json: String from tape",
7015+ symbol: "tape:enjs:format",
7016+ usage: "zuse",
7017+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#tapeenjsformat",
7018+ desc: "Used in the Zuse library.",
7019+ },
7020+ {
7021+ name: "Encode json: Millisecond timestamp",
7022+ symbol: "time:enjs:format",
7023+ usage: "zuse",
7024+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#timeenjsformat",
7025+ desc: "Used in the Zuse library.",
7026+ },
7027+ {
7028+ name: "Cord to line list",
7029+ symbol: "to-wain:format",
7030+ usage: "zuse",
7031+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#to-wainformat",
7032+ desc: "Used in the Zuse library.",
7033+ },
7034+ {
7035+ name: "Decode json: Unit fall",
7036+ symbol: "uf:dejs:format",
7037+ usage: "zuse",
7038+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#ufdejsformat",
7039+ desc: "Used in the Zuse library.",
7040+ },
7041+ {
7042+ name: "Decode json (unit): Null",
7043+ symbol: "ul:dejs-soft:format",
7044+ usage: "zuse",
7045+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#uldejs-softformat",
7046+ desc: "Used in the Zuse library.",
7047+ },
7048+ {
7049+ name: "Decode json: Null",
7050+ symbol: "ul:dejs:format",
7051+ usage: "zuse",
7052+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#uldejsformat",
7053+ desc: "Used in the Zuse library.",
7054+ },
7055+ {
7056+ name: "Decode json: Unit need",
7057+ symbol: "un:dejs:format",
7058+ usage: "zuse",
7059+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#undejsformat",
7060+ desc: "Used in the Zuse library.",
7061+ },
7062+ {
7063+ name: "Encode json: String from wall",
7064+ symbol: "wall:enjs:format",
7065+ usage: "zuse",
7066+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_1-5/#wallenjsformat",
7067+ desc: "Used in the Zuse library.",
7068+ },
7069+ {
7070+ name: "Decode json (unit): Full unit pole",
7071+ symbol: "za:dejs-soft:format",
7072+ usage: "zuse",
7073+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#zadejs-softformat",
7074+ desc: "Used in the Zuse library.",
7075+ },
7076+ {
7077+ name: "Decode json: Full unit pole",
7078+ symbol: "za:dejs:format",
7079+ usage: "zuse",
7080+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#zadejsformat",
7081+ desc: "Used in the Zuse library.",
7082+ },
7083+ {
7084+ name: "Decode json (unit): Collapse unit list",
7085+ symbol: "zl:dejs-soft:format",
7086+ usage: "zuse",
7087+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#zldejs-softformat",
7088+ desc: "Used in the Zuse library.",
7089+ },
7090+ {
7091+ name: "Decode json: Collapse unit list",
7092+ symbol: "zl:dejs:format",
7093+ usage: "zuse",
7094+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#zldejsformat",
7095+ desc: "Used in the Zuse library.",
7096+ },
7097+ {
7098+ name: "Decode json (unit): Collapse unit map",
7099+ symbol: "zm:dejs-soft:format",
7100+ usage: "zuse",
7101+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#zmdejs-softformat",
7102+ desc: "Used in the Zuse library.",
7103+ },
7104+ {
7105+ name: "Decode json: Collapse unit map",
7106+ symbol: "zm:dejs:format",
7107+ usage: "zuse",
7108+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#zmdejsformat",
7109+ desc: "Used in the Zuse library.",
7110+ },
7111+ {
7112+ name: "Decode json (unit): Unit tuple",
7113+ symbol: "zp:dejs-soft:format",
7114+ usage: "zuse",
7115+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_7/#zpdejs-softformat",
7116+ desc: "Used in the Zuse library.",
7117+ },
7118+ {
7119+ name: "Decode json: Unit tuple",
7120+ symbol: "zp:dejs:format",
7121+ usage: "zuse",
7122+ slug: "https://urbit.org/docs/hoon/reference/zuse/2d_6/#zpdejsformat",
7123+ desc: "Used in the Zuse library.",
7124+ },
65297125];
pages/index.js+4−4
@@ -26,7 +26,7 @@ import { useLocalStorage } from "../lib/hooks";
2626
2727const Banner = ({ children, isOpen, href, dismiss }) => {
2828 return (
29− <div className="w-full flex justify-center bg-blue-100">
29+ <div className="w-full flex justify-center bg-green-100">
3030 <SingleColumn>
3131 <div className="w-full layout">
3232 <div className="w-full flex justify-between items-center px-4 md:px-8 py-4">
@@ -34,7 +34,7 @@ const Banner = ({ children, isOpen, href, dismiss }) => {
3434 {children}
3535 </a>
3636 <button
37− className="type-ui w-6 h-6 bg-blue-400 flex items-center justify-center rounded-full text-white hover:opacity-70"
37+ className="type-ui w-6 h-6 bg-green-400 flex items-center justify-center rounded-full text-white hover:opacity-70"
3838 onClick={(e) => {
3939 e.stopPropagation();
4040 dismiss();
@@ -91,10 +91,10 @@ export default function Home({ posts, events, openGrantsCount, search }) {
9191 if (isBannerOpen) {
9292 return (
9393 <Banner
94− href="https://twitter.com/zodisok"
94+ href="https://assembly.urbit.org"
9595 dismiss={() => setBanner(false)}
9696 >
97− <p className="text-blue-400 font-semibold hover:opacity-70">{`-> New network update coming soon. Follow along @zodisok.`}</p>
97+ <p className="text-green-400 font-semibold hover:opacity-70">{`-> Network update is live. Learn more at Assembly 2021.`}</p>
9898 </Banner>
9999 );
100100 } else {
pages/using/[[...slug]].js+3−3
@@ -16,7 +16,7 @@ const breadcrumbs = (posts, paths) => {
1616 const results = [
1717 <Link href="/">Urbit</Link>,
1818 <span className="px-1">/</span>,
19− <Link href="/using">Operator's Manual</Link>,
19+ <Link href="/using">User's Manual</Link>,
2020 ];
2121 let thisLink = "/using";
2222 for (const path of paths) {
@@ -102,7 +102,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
102102 return (
103103 <>
104104 <Head>
105− <title>{data.title} • Operator's Manual • urbit.org</title>
105+ <title>{data.title} • User's Manual • urbit.org</title>
106106 {Meta(data)}
107107 </Head>
108108 <div className="flex w-screen h-screen min-h-screen w-screen sidebar">
@@ -113,7 +113,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
113113 breadcrumbs={breadcrumbs(posts, params.slug?.slice(0, -1) || "")}
114114 title={data.title}
115115 search={search}
116− section={"Operator's Manual"}
116+ section={"User's Manual"}
117117 params={params}
118118 >
119119 <div className="markdown">
vercel.json+5
@@ -3,6 +3,11 @@
33 "silent": true
44 },
55 "redirects": [
6+ {
7+ "source": "/using/os/getting-started",
8+ "destination": "/using/os/basics",
9+ "permanent": true
10+ },
611 {
712 "source": "/grants/(apprenticeships|proposals|bounties)/:page",
813 "destination": "/grants/:page",