1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
6#[serde(rename_all = "camelCase")]
7pub struct TabularDataResource {
8 #[serde(skip_serializing_if = "Option::is_none")]
9 pub path: Option<PathOrPaths>,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub data: Option<Vec<serde_json::Value>>,
12 pub schema: TableSchema,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub title: Option<String>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub description: Option<String>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub homepage: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub sources: Option<Vec<Source>>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub licenses: Option<Vec<License>>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub dialect: Option<Dialect>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub format: Option<String>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub mediatype: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub encoding: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub bytes: Option<i64>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub hash: Option<String>,
35}
36
37#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
38#[serde(untagged)]
39pub enum PathOrPaths {
40 Single(String),
41 Multiple(Vec<String>),
42}
43
44#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
45#[serde(rename_all = "camelCase")]
46pub struct TableSchema {
47 pub fields: Vec<TableSchemaField>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub primary_key: Option<PrimaryKey>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub foreign_keys: Option<Vec<ForeignKey>>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub missing_values: Option<Vec<String>>,
54}
55
56#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
57#[serde(rename_all = "camelCase", untagged)]
58pub enum PrimaryKey {
59 Single(String),
60 Multiple(Vec<String>),
61}
62
63#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
64#[serde(rename_all = "camelCase")]
65pub struct ForeignKey {
66 pub fields: ForeignKeyFields,
67 pub reference: ForeignKeyReference,
68}
69
70#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
71#[serde(untagged)]
72pub enum ForeignKeyFields {
73 Single(String),
74 Multiple(Vec<String>),
75}
76
77#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
78#[serde(rename_all = "camelCase")]
79pub struct ForeignKeyReference {
80 pub resource: String,
81 pub fields: ForeignKeyFields,
82}
83
84#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
85#[serde(rename_all = "camelCase")]
86pub struct TableSchemaField {
87 pub name: String,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub title: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub description: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub example: Option<String>,
94 #[serde(rename = "type")]
95 pub field_type: FieldType,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub format: Option<FieldFormat>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub constraints: Option<HashMap<String, serde_json::Value>>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub rdf_type: Option<String>,
102}
103
104#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
105#[serde(rename_all = "lowercase")]
106pub enum FieldType {
107 String,
108 Number,
109 Integer,
110 Date,
111 Time,
112 Datetime,
113 Year,
114 Yearmonth,
115 Boolean,
116 Object,
117 Geopoint,
118 Geojson,
119 Array,
120 Duration,
121 #[default]
122 Any,
123}
124
125#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
126#[serde(rename_all = "lowercase")]
127pub enum FieldFormat {
128 Default,
129 Email,
130 Uri,
131 Binary,
132 Uuid,
133 Any,
134 Array,
135 Object,
136}
137
138#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
139#[serde(rename_all = "camelCase")]
140pub struct Source {
141 pub title: String,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub path: Option<String>,
144 #[serde(skip_serializing_if = "Option::is_none")]
145 pub email: Option<String>,
146}
147
148#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
149#[serde(rename_all = "camelCase")]
150pub struct License {
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub name: Option<String>,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub path: Option<String>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub title: Option<String>,
157}
158
159#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
160#[serde(rename_all = "camelCase")]
161pub struct Dialect {
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub delimiter: Option<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub double_quote: Option<bool>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub line_terminator: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub null_sequence: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub quote_char: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub escape_char: Option<String>,
174 #[serde(skip_serializing_if = "Option::is_none")]
175 pub skip_initial_space: Option<bool>,
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub header: Option<bool>,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub comment_char: Option<String>,
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub case_sensitive_header: Option<bool>,
182}