feat: initial commit

This commit is contained in:
əlemi 2024-03-21 23:56:01 +01:00
commit 64cd23e388
Signed by: alemi
GPG key ID: A4895B84D311642C
7 changed files with 599 additions and 0 deletions

10
.editorconfig Normal file
View file

@ -0,0 +1,10 @@
# Default to Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
indent_size = 4
[*.rs]
indent_size = 2

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1
.rustfmt.toml Normal file
View file

@ -0,0 +1 @@
hard_tabs = true

329
Cargo.lock generated Normal file
View file

@ -0,0 +1,329 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bumpalo"
version = "3.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
[[package]]
name = "cc"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "jrd"
version = "0.1.0"
dependencies = [
"chrono",
"serde",
"serde_json",
]
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "2.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"

19
Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "jrd"
version = "0.1.0"
edition = "2021"
authors = [ "alemi <me@alemi.dev>" ]
description = "json resource descriptor, as specified by https://www.packetizer.com/json/jrd/"
license = "MIT"
keywords = ["json", "jrd", "web", "serialize"]
repository = "https://git.alemi.dev/jrd.git"
readme = "README.md"
[lib]
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
[dev-dependencies]
serde_json = "1"

12
README.md Normal file
View file

@ -0,0 +1,12 @@
# jrd
> json resource descriptor, as specified by https://www.packetizer.com/json/jrd/
this tiny crate provides a struct representation for Json Resource Descriptors, with serde traits derived
get more information on its usage on [docs.rs](https://docs.rs/jrd/latest/jrd)
## why
this crate is tiny and does very little, mostly piggy-backing from Packetizer's documentation
i found myself writing this and the docs for myself while working on a project, to have better
hints around JRDs, so I thought others might find it useful and decided to share it publicly

227
src/lib.rs Normal file
View file

@ -0,0 +1,227 @@
//! # JRD
//!
//! from [Packetizer](https://www.packetizer.com/json/jrd/):
//! > The JSON Resource Descriptor (JRD) is a simple [JSON](https://www.techabulary.com/j/json/) object that describes a "resource" on the Internet,
//! > where a "resource" is any entity on the Internet that is identified via a URI or IRI.
//! > For example, a person's account URI (e.g., acct:bob@example.com) is a resource.
//! > So are all web URIs (e.g., https://www.packetizer.com/).
//!
//!
//! > The JSON Resource Descriptor, originally introduced in [RFC 6415](https://www.packetizer.com/rfc/rfc6415/) and
//! > based on the Extensible Resource Descriptor (XRD) format, was adopted for use
//! > in the [WebFinger](https://www.techabulary.com/w/webfinger/) protocol, though its use is not restricted
//! > to WebFinger or RFC 6415.
//!
//! This tiny crate provides a struct representation of JRDs, [JsonResourceDescriptor], together with
//! [serde::Serialize] and [serde::Deserialize] implementations.
//!
//! All documentation is copied as-is from packetizer.com.
//!
//! # usage
//! ```rust
//! let jrd_string = r#"{
//! "subject": "acct:paulej@packetizer.com",
//! "properties": {
//! "http://packetizer.com/ns/name": "Paul E. Jones"
//! },
//! "links": [
//! {
//! "rel": "http://webfinger.net/rel/profile-page",
//! "href": "http://www.packetizer.com/people/paulej/"
//! },
//! {
//! "rel": "http://packetizer.com/rel/blog",
//! "type": "text/html",
//! "href": "http://www.packetizer.com/people/paulej/blog/",
//! "titles": {
//! "en-us": "Paul E. Jones' Blog"
//! }
//! }
//! ]
//! }"#;
//!
//! let jrd_struct = jrd::JsonResourceDescriptor {
//! subject: "acct:paulej@packetizer.com".into(),
//! aliases: Vec::new(),
//! properties: [("http://packetizer.com/ns/name".to_string(), "Paul E. Jones".to_string())].into(),
//! expires: None,
//! links: vec![
//! jrd::JsonResourceDescriptorLink {
//! rel: "http://webfinger.net/rel/profile-page".into(),
//! href: Some("http://www.packetizer.com/people/paulej/".into()),
//! link_type: None,
//! titles: jrd::Map::default(),
//! properties: jrd::Map::default(),
//! },
//! jrd::JsonResourceDescriptorLink {
//! rel: "http://packetizer.com/rel/blog".into(),
//! href: Some("http://www.packetizer.com/people/paulej/blog/".into()),
//! link_type: Some("text/html".into()),
//! titles: [("en-us".to_string(), "Paul E. Jones' Blog".to_string())].into(),
//! properties: jrd::Map::default(),
//! },
//! ],
//! };
//!
//! // deserialize
//! assert_eq!(serde_json::from_str::<jrd::JsonResourceDescriptor>(jrd_string).unwrap(), jrd_struct);
//!
//! // serialize
//! assert_eq!(serde_json::to_string_pretty(&jrd_struct).unwrap(), jrd_string)
//! ```
pub type Map = std::collections::BTreeMap<String, String>;
pub type Time = chrono::DateTime<chrono::Utc>;
/// The JSON Resource Descriptor (JRD) is a simple JSON object that describes a "resource" on the Internet, where a "resource" is any entity on the Internet that is identified via a URI or IRI.
///
/// For example, a person's account URI (e.g., acct:bob@example.com) is a resource. So are all web URIs (e.g., https://www.packetizer.com/).
/// The JSON Resource Descriptor, originally introduced in [RFC 6415](https://www.packetizer.com/rfc/rfc6415/) and based on the Extensible Resource Descriptor (XRD) format,
/// was adopted for use in the WebFinger protocol, though its use is not restricted to WebFinger or [RFC 6415](https://www.packetizer.com/rfc/rfc6415/).
/// A JRD object comprises the following name/value pairs:
/// * expires
/// * subject
/// * aliases
/// * properties
/// * links
///
/// A JRD describes a URI or IRI by returning structured information about the identifier.
/// For example, a JRD that describes a person named Paul might include information about Paul's full name, homepage, blog, etc.
///
/// Here is an example JRD that describes a user named Paul:
/// ```json
/// {
/// "subject" : "acct:paulej@packetizer.com",
/// "properties" :
/// {
/// "http://packetizer.com/ns/name" : "Paul E. Jones"
/// },
/// "links" :
/// [
/// {
/// "rel" : "http://webfinger.net/rel/profile-page",
/// "href" : "http://www.packetizer.com/people/paulej/"
/// },
/// {
/// "rel" : "http://packetizer.com/rel/blog",
/// "type" : "text/html",
/// "href" : "http://www.packetizer.com/people/paulej/blog/",
/// "titles" :
/// {
/// "en-us" : "Paul E. Jones' Blog"
/// }
/// }
/// ]
/// }
/// ```
#[derive(Debug, Clone, Eq, PartialEq, Default, serde::Serialize, serde::Deserialize)]
pub struct JsonResourceDescriptor {
/// The value of the "subject" member is an URI that identifies the entity that the JRD describes.
/// The “subject” member SHOULD be present in the JRD.
pub subject: String,
/// The “aliases” array is an array of zero or more URI strings that identify the same entity as the “subject” URI.
/// The “aliases” member is OPTIONAL in the JRD.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub aliases: Vec<String>,
/// The “properties” object comprises zero or more name/value pairs whose names are URIs (referred to as “property identifiers”) and whose values are strings or null.
///
/// Properties are used to convey additional information about the subject of the JRD. As an example, consider this use of “properties”:
/// ```json
/// "properties" : { "http://packetizer.com/ns/name" : "Bob Smith" }
/// ```
/// The “properties” member is optional.
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub properties: Map,
/// The value of the “expires” member is a string that indicates the date and time after which the JRD SHOULD be considered expired and no longer utilized.
///
/// This format is formally defined in RFC 3339. The “expires” member MUST NOT use fractional seconds and MUST express time only Universal Coordinate Time via the “Z” designation on the end of the string.
/// An example of the “expires” member is:
/// ```json
/// "expires" : "2012-11-16T19:41:35Z"
/// ```
///
/// The “expires” member is OPTIONAL in the JRD, but should be honored if present.
/// Note: The “expires” member is not defined for use with WebFinger, but is defined for Host Metadata ([RFC 6415](https://www.packetizer.com/rfc/rfc6415/)). For WebFinger, this member MUST NOT be transmitted and ignored if received.
#[serde(skip_serializing_if = "Option::is_none")]
pub expires: Option<Time>,
/// The “links” array has any number of member objects (see [JsonResourceDescriptorLink]), each of which represents a link.
///
/// The “links” array is OPTIONAL in the JRD.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub links: Vec<JsonResourceDescriptorLink>,
}
/// Each of these link objects can have the following members:
/// * rel
/// * type
/// * href
/// * titles
/// * properties
///
/// The “rel” and “href” members are strings representing the link's relation type and the target URI, respectively. The context of the link is the “subject”.
/// The “type” member is a string indicating what the media type of the result of dereferencing the link ought to be.
/// The order of elements in the “links” array MAY be interpreted as indicating an of preference. Thus, if there are two or more link relations having the same “rel” value, the first link relation would indicate the users preferred link.
#[derive(Debug, Clone, Eq, PartialEq, Default, serde::Serialize, serde::Deserialize)]
pub struct JsonResourceDescriptorLink {
/// The value of the “rel” member is a string that is either a URI or a registered relation type (see [RFC 8288](https://www.packetizer.com/rfc/rfc8288/)).
///
/// The value of the “rel” member MUST contain exactly one URI or registered relation type. The URI or registered relation type identifies the type of the link relation.
/// The other members of the object have meaning only once the type of link relation is understood.
/// In some instances, the link relation will have associated semantics enabling the client to query for other resources on the Internet.
/// In other instances, the link relation will have associated semantics enabling the client to utilize the other members of the link relation object without fetching additional external resources.
/// URI link relation type values are compared using the "Simple String Comparison" algorithm of Section 6.2.1 of [RFC 3986](https://www.packetizer.com/rfc/rfc3986/).
///
/// The “rel” member MUST be present in a link relation object.
pub rel: String,
/// The value of the “type” member is a string that indicates the media type of the target resource (see [RFC 6838](https://www.packetizer.com/rfc/rfc6838/)).
/// The “type” member is OPTIONAL in a link relation object.
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub link_type: Option<String>,
/// The value of the “href” member is a string that contains an URI pointing to the linked resource.
/// The “href” member is optional in the link relation object.
#[serde(skip_serializing_if = "Option::is_none")]
pub href: Option<String>,
/// The “titles” object comprises zero or more name/value pairs whose names are a language tag or the string “und”.
///
/// The string is human-readable and describes the link relation.
/// More than one title for the link relation MAY be provided for the benefit of users who utilize the link relation, and, if used, a language identifier SHOULD be duly used as the name.
/// If the language is unknown or unspecified, then the name is “und”.
///
/// A JRD SHOULD NOT include more than one title named with the same language tag (or “und”) within the link relation object.
/// Meaning is undefined if a link relation object includes more than one title identified with the same language tag (or “und”), though this MUST NOT be treated as an error.
/// A client MAY select whichever title or titles it wishes to utilize.
///
/// Here is an example of the “titles” object:
/// ```json
/// "titles" :
/// {
/// "und" : "The Magical World of Steve",
/// "en-us" : "The Magical World of Steve",
/// "fr" : "Le Monde Magique de Steve"
/// }
/// ```
/// The “titles” member is OPTIONAL in a link relation object.
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub titles: Map,
/// The “properties” object within the link relation object comprises zero or more name/value pairs whose names are URIs (referred to as “property identifiers”) and whose values are strings or null.
///
/// Properties are used to convey additional information about the link relation.
/// As an example, consider this use of “properties”:
/// ```json
/// "properties" : { "http://packetizer.com/ns/port" : "993" }
/// ```
/// The “properties” member is optional in a link relation object.
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub properties: Map,
}