forked from fastn-stack/ftd.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathor-type.ftd
110 lines (74 loc) · 2.64 KB
/
or-type.ftd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/-- ft-core.concept:
-- ft.page-with-toc: `or-type`
toc: $config.data-toc
sub-sections: $config.doc-header
-- ft.markdown:
`ftd` supports `or-type`, which is loosely equivalent of `enum` in Rust, and is
otherwise known as ["algebraic data
type"](https://en.wikipedia.org/wiki/Algebraic_data_type).
-- ft.h1: Declaring an `or-type`
Say we have a sales business and we are going to get "leads", and a lead can be
either an individual or a company. In case of individuals we have fields like
their name, and phone number. For a company we have company name and the name of
contact and the fax number of the company.
An `or-type` can be created like this:
-- ft.code:
lang: ftd
\-- or-type lead:
\--- individual:
name: caption
phone: string
\--- company:
name: caption
contact: string
fax: string
-- ft.markdown:
Here we have used `ftd::p1`'s "sub-section" to represent each possibilities.
The declarations `individual` or `company`, are called `or-type` variants, and they
use similar syntax as [`record` declarations](record/).
-- ft.h1: `or-type` variables
A variable can be created like this:
-- ft.code:
lang: ftd
\-- var amitu: Amit Upadhyay
type: lead.individual
phone: 1231231231
\-- var acme: Acme Inc.
type: lead.company
contact: John Doe
fax: +1-234-567890
-- ft.markdown:
Note that in the `type` we have included the `or-type` as well as the exact
`variant` we want to construct.
-- ft.h1: Reading An `or-type` From Rust
An `or-type` in `ftd` is equivalent of a `enum` in Rust.
-- ft.h2: Rust Type
To read the above `ftd` file from Rust we have to first create an `enum` in Rust
that is compatible with our `lead` definition:
-- ft.code:
lang: rs
#[allow(non_camel_case_types)]
#[derive(serde::Deserialize)]
#[serde(tag = "type")]
enum Lead {
individual { name: String, phone: String },
company { name: String, contact: String, fax: String },
}
-- ft.markdown:
For each variant in `lead` `or-type`, we have a corresponding clause in `Lead`
`enum`.
Note: We have to match the case of enum variant with the one used in `ftd`, `ftd`
has a naming convention with lower case, where as Rust prefers CamelCase, so we
have used `#[allow(non_camel_case_types)]`.
Note: Each `enum` must have `#[serde(tag = "type")]` as this is how we track which
variant is represented in data.
-- ft.h2: Getting Data From FTD File
Once the mapping is in place, we can use the `ftd` crate to parse an `ftd` file,
and get data out of it:
-- ft.code:
lang: rs
let doc = ftd::p2::Document::from("some/id", source, lib)?;
let amitu: Lead = doc.get("amitu")?;
-- ft.markdown:
You can read more details of reading `ftd` files ["Reading FTD
Files"](reading-data/) guide.