SpruceKit
SpruceID
  • 🌲SpruceKit Introduction
    • Decentralized Identity Overview
    • Glossary
  • ⚡Quickstart
  • SpruceKit Mobile
    • SpruceKit Showcase App
      • Installation
      • Getting Started
      • Issue a Showcase Credential
      • Present a Showcase Credential
    • SpruceKit Mobile SDK
      • Introduction
      • Core Components
        • StorageManager
        • KeyManager
        • CredentialPack
        • Card
        • IsoMdlPresentation
        • mDocReader/IsomDLReader
        • Document Scanner
      • SpruceKit iOS SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
      • SpruceKit Android SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present an mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
  • Verifiable Digital Credentials
    • ⚙️DIDKit
      • Installation
      • Core Concepts
      • DID Methods
      • Runtime Configuration
      • Specifications and Dependencies
      • Quickstart
      • DIDKit Packages
        • Command Line Interface
        • HTTP Server
        • Rust Crate
        • C Interface
        • Java and Android
        • Python
        • Javascript
      • DIDKit Examples
        • Core Functions (CLI)
        • Core Functions (HTTP)
        • did-web in minutes
        • Batch Generation & Verification
    • 🪪ISO mDL
      • Quickstart
      • Core Concepts
      • User Guide
  • Schema Definition Language
    • 🔗TreeLDR
      • TreeLDR Quickstart
        • First Schema
        • Compilation into JSON Schema
        • Compilation into JSON-LD Context
        • Writing a Layout
        • Simple Rust Integration
      • Types
        • Literal Types
      • Layouts
        • Primitive Layouts
        • Literal Layouts
        • Enumeration
        • Array Layout
        • References
      • Compiling
        • Schema Definition Formats
          • JSON Schema
          • JSON-LD Context
          • Resource Description Framework (RDF)
        • Programming Languages
          • Compiling to Rust
      • RDF Vocabulary
      • 💡TreeLDR Basics
        • Types and Layouts
        • Properties
        • Syntax
  • Witness for Credential Claims
    • 🔭Rebase
      • Core Library
      • Rust Client/Witness SDK
      • WASM Client SDK
      • Simple "Basic Post" Schema
      • DNS Witness Flow Schema
  • References
    • Contributing
    • Code of Conduct
Powered by GitBook
On this page
  • Types
  • Layouts

Was this helpful?

  1. Schema Definition Language
  2. TreeLDR
  3. TreeLDR Basics

Types and Layouts

A TreeLDR document is a collection of types and layouts.

Types

A type, sometimes called class, sort, or schema in other languages, is an object that describes the properties associated with a value instance of this type. In TreeLDR, types are simply declared using the type keyword:

type MyType; // Declares that `MyType` is a type.

In the example above, MyType is an empty type, and it doesn't say anything about the instances of MyType. We can extend this definition by listing all the properties of this type between braces:

type MyType {
	property1: Type1,
	// ...
	propertyN: TypeN
}

This specifies that each instance of MyType can have the above properties. By default those properties are optional. This can be changed using the required keyword:

type MyType {
	property1: required Type1,
	// ...
	propertyN: TypeN
}

Now each instance of MyType must have the property1 property. In this context, required is an attributes to the property1 property. Another useful attribute is multiple that states that a property can be associated with more than one value at once. Without attributes, properties are all optional and can take at most a single value.

Here is an example defining the Person type taking advantage of property attributes:

use <http://www.w3.org/2001/XMLSchema#> as xs;

/// A person.
type Person {
	/// Full name.
	name: required xs:string,

	/// Parents.
	parent: multiple Person,

	/// Age.
	age: xs:nonNegativeInteger
}

Layouts

When writing an application, one may need to represent the same data into multiple formats (one format inside the database, another in memory, transmission, etc.). In TreeLDR, those formats are called layouts. A layout is a particular representation for a type. It is sometimes called a view in other languages.

A layout defines a list of properties to include, how to name them (each property can have different name in different layouts), how to order them, and more. A layout is defined using the layout keyword. A single type can have multiple layouts.

/// A layout for `MyType` that includes every properties.
layout MyLayout for MyType {
	property1 as name1: Layout1,
	// ...
	propertyN as nameN: LayoutN
}

/// Another layout for `MyType` that only includes the first property.
layout MyOtherLayout for MyType {
	property1 as otherName: OtherLayout1
}

The as keyword is used to rename the considered property inside the layout. Without it, a default name is extracted from the identifier of the property. Here is a layout definition for the Person type defined above:

layout PersonLayout for Person {
	name as fullName: required xs:string,
	parent as parents: multiple PersonLayout,
	age: xs:nonNegativeInteger
}

Layouts are used to define a common representation for a given type that can be shared between applications. TreeLDR can export a layout definition into type definitions in different programming languages, and schema definitions for data exchange formats. For instance using the TreeLDR compiler, the PersonLayout schema definition above can be translated into the following:

  • A Rust type

pub struct PersonLayout {
	full_name: String,
	parents: BTreeSet<PersonLayout>,
	age: Option<u32>
}
  • A TypeScript type

type PersonLayout = {
	fullName: string;
	parents?: Array<PersonLayout>,
	age?: number
}
  • A JSON Schema

{
	"type": "object",
	"properties": {
		"fullName": {
			"type": "string"
		},
		"parents": {
			"type": "array",
			"item": {
				"$ref": "https://example.com/PersonLayout.schema.json"
			}	
		},
		"age": {
			"type": "integer"
		}
	},
	"required": [
		"fullName"
	]
}

These define a common representation that can be used to exchange instances of Person between a Rust application and a TypeScript application using JSON as the intermediate format. TreeLDR will also take care of generating the JSON serialization/deserialization routines in both languages, matching the above JSON Schema.

Default Layout

Each type definition is always also an implicit layout definition. If you consider again the previous Person type definition:

use <http://www.w3.org/2001/XMLSchema#> as xs;

/// A person.
type Person {
	/// Full name.
	name: required xs:string,

	/// Parents.
	parent: multiple Person,

	/// Age.
	age: xs:nonNegativeInteger
}

This definition implicitly embeds the following layout definition:

/// A person.
layout Person for Person {
	/// Full name.
	name: required xs:string,

	/// Parents.
	parent: multiple Person,

	/// Age.
	age: xs:nonNegativeInteger
}

It is possible to use layout-specific keywords (such as the as keyword to rename properties inside a layout) to affect the default layout definition. It is also possible to replace the default layout definition using the with keyword:

layout Person for Person {
	name: required xs:string,
	parent: multiple Person,
	age: xs:nonNegativeInteger
} with { // the default layout only includes the `name` property.
	name: required xs:string
}
PreviousTreeLDR BasicsNextProperties

Last updated 1 year ago

Was this helpful?

🔗
💡