record
ftd
supports record
types. These are also called struct
in some languages.
Declaring a record
Before a record can be used it must be declared using the record
syntax:
Declaring a Person record
-- record person: caption name: integer age: optional body bio:
Here we are creating a record. The name of the record is person
. It has three fields: name
, age
and bio
.
Declaring a Company record
-- record company: caption name: person list employees:
In this case, the name of the record is company
. It has two fields: caption name
and list of employees
of person
type.
Declaring a record
with default values
Sometimes, the programmer might want to provide default values to the record fields, in case if he/she doesn’t specify those during initialization.
Declaring a Person record with default field values
-- record person: caption name: Undefined integer age: optional body bio: Not specified ;; << Alternative way >> -- record person: caption name: Undefined integer age: -- optional body person.bio: No bio is specified for this person.
Declaring a Company record with default field values
-- record company: string name: FifthTry -- person list company.employees: -- person: name: Arpita age: 22 -- person: name: Abrar age: 24 -- end: company.employees
Field Types
Fields can be either one of the built-in types, another type like a record
or or-type
.
Record Variable
A variable can be created with type record
:
-- person john-snow: John Snow age: 14
Here we have created a new variable of type person
, called it amitu
, and the value of name
, since its declared as caption
in the record definition, is read from the “caption” area, and age
is read from the “header”.
Note that we have not passed bio
, since bio
is declared as optional body
, so it’s not a problem. Had it been body
the above would not have been valid.
Record Field Update Syntax
The field which needs to be updated has to be mutable before updating its value. An individual field of a record can be updated using a syntax like this:
-- person $john-snow: John Snow $age: 14 -- $john-snow.age: 15
Here we have used -- $john-snow.age: 15
to update a single field of a record.
This also works if the field is a list:
-- record person: caption name: string list alias: -- person $john-snow: John Snow -- $john-snow.alias: Aegon Targaryen -- $john-snow.alias: Lord Crow -- $john-snow.alias: The White Wolf -- $john-snow.alias: The Prince That Was Promised
Reading A Record From Rust
A record
in ftd
is equivalent of a struct
in Rust.
Rust Type
To read the above ftd
file from Rust you will have to first create a struct
in Rust that is compatible with our person
definition:
#[derive(serde::Deserialize)] struct Person { name: String, age: i32, bio: Option<String>, }
For each field in person
record, we have a corresponding field in our Person
struct
.
Note that we used age
as i32, but it could have been any type that can be deserialised from JSON Number since ftd
integer
is converted to JSON Number
.
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:
let doc = ftd::p2::Document::from("some/id", source, lib)?; let amitu: Person = doc.get("amitu")?;
You can read more details of reading ftd
files “Reading FTD Files” guide.
Record “Instances”
ftd
also supports “anonymous” instances:
-- person: Amit Upadhyay age: 40 This is the bio -- person: Shobhit Sharma age: 30
Note that we have not assigned these instances to any variable using the var
keyword. These are called “anonymous instances”.
These instances can be read from Rust using:
let doc = ftd::p2::Document::from("some/id", source, lib)?; let instances: Vec<Person> = doc.instances("person")?; // if you expect the document to contain only one instance: let instance: Person = doc.only_instance("person")?;
This allows you an “ergonomic” way to declare data in ftd
files.