diff --git a/.github/actions/install-rust-toolchain/action.yml b/.github/actions/install-rust-toolchain/action.yml
new file mode 100644
index 00000000..b89712a6
--- /dev/null
+++ b/.github/actions/install-rust-toolchain/action.yml
@@ -0,0 +1,23 @@
+name: Install Rust Toolchain
+description: |
+ Installs the Rust toolchain.
+ Relies on the fact that rustup show will install a toolchain. The installed version is based on a toolchain file, or stable if no such file is found.
+inputs:
+ components:
+ description: A list of additional components to install
+ required: false
+ default: null
+runs:
+ using: "composite"
+ steps:
+ - name: Install Rust Toolchain
+ # A note on using rustup show to do this (from https://rust-lang.github.io/rustup/overrides.html):
+ # To verify which toolchain is active, you can use rustup show,
+ # which will also try to install the corresponding toolchain if the current one has not been installed [...].
+ # (Please note that this behavior is subject to change, as detailed in issue #1397 [https://github.com/rust-lang/rustup/issues/1397].)
+ run: rustup show
+ shell: bash
+ - name: Install Additional Components
+ run: rustup component add ${{ inputs.components }}
+ shell: bash
+ if: ${{ inputs.components != null }}
\ No newline at end of file
diff --git a/.github/workflows/notice-generation.yml b/.github/workflows/notice-generation.yml
index e53183ab..ac1813d8 100644
--- a/.github/workflows/notice-generation.yml
+++ b/.github/workflows/notice-generation.yml
@@ -16,8 +16,8 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- - name: Install stable toolchain
- run: rustup show
+ - name: Install toolchain
+ uses: ./.github/actions/install-rust-toolchain
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1
- name: Generate the Notice
diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml
index c5d5780f..6e7ea40e 100644
--- a/.github/workflows/rust-ci.yml
+++ b/.github/workflows/rust-ci.yml
@@ -21,23 +21,20 @@ jobs:
submodules: recursive
- name: Install protobuf-compiler
run: sudo apt-get install -y protobuf-compiler
- - name: Install nightly Rust toolchain
- uses: actions-rs/toolchain@v1
+ - name: Install .NET 7.0
+ uses: actions/setup-dotnet@v3
with:
- toolchain: nightly-2022-08-11
- default: true
- override: true
- components: clippy, rustfmt
+ dotnet-version: 7.0
+ - name: Install Rust toolchain
+ uses: ./.github/actions/install-rust-toolchain
+ with:
+ components: clippy rustfmt
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- run: cargo check --workspace
- # Note: cargo check should use the --locked option
- # Excluding it because of this known issue: https://github.com/mozilla/uniffi-rs/issues/1032
- run: cargo clippy --all-targets --all-features --workspace --no-deps -- -D warnings
- run: cargo fmt --all -- --check
- name: Run doctest only
- # we run doctests here as cargo tarpaulin (our test runner)
- # requires nightly toolchain to do so
uses: actions-rs/cargo@v1
with:
command: test
@@ -58,12 +55,12 @@ jobs:
submodules: recursive
- name: Install protobuf-compiler
run: sudo apt-get install -y protobuf-compiler
- - name: Install nightly Rust toolchain
- uses: actions-rs/toolchain@v1
+ - name: Install .NET 7.0
+ uses: actions/setup-dotnet@v3
with:
- toolchain: nightly-2022-08-11
- default: true
- override: true
+ dotnet-version: 7.0
+ - name: Install Rust toolchain
+ uses: ./.github/actions/install-rust-toolchain
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Build
diff --git a/Cargo.toml b/Cargo.toml
index cc40e80f..43136353 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,12 +17,12 @@ members = [
# extension
"core/module/managed_subscribe",
+ # DTDL tools
+ "dtdl-tools",
+
# digital twin model
"digital-twin-model",
- # DTDL parser
- "dtdl-parser",
-
# samples
"samples/common",
"samples/protobuf_data_access",
@@ -31,7 +31,7 @@ members = [
"samples/mixed",
"samples/property",
"samples/seat_massager",
- "samples/streaming",
+ # "samples/streaming",
]
[workspace.dependencies]
diff --git a/README.md b/README.md
index 0532aa85..81656c9f 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,6 @@
- [Cloning the Repo](#cloning-the-repo)
- [Developer Notes](#developer-notes)
- [JSON-LD Crate](#json-ld-crate)
- - [DTDL Parser](#dtdl-parser)
- [Building](#building)
- [Running the Tests](#running-the-tests)
- [Running the Samples](#running-the-samples)
@@ -96,10 +95,6 @@ However, it currently has a build issue that is discussed [here](https://github.
To work around this issue you will need to use git clone to obtain the source from [here](https://github.com/blast-hardcheese/json-ld)
and checkout its "resolve-issue-40" branch. It should be cloned to a directory that is a sibling to ibeji.
-### DTDL Parser
-
-There is no existing DTDL Parser for Rust, so we have provided a minimalistic one for DTDL v2 that is based on the [JavaScript DTDL Parser](https://github.com/Azure/azure-sdk-for-js/tree/%40azure/dtdl-parser_1.0.0-beta.2/sdk/digitaltwins/dtdl-parser).
-
## Building
Once you have installed the prerequisites, go to your enlistment's root directory and run:
diff --git a/core/invehicle-digital-twin/src/main.rs b/core/invehicle-digital-twin/src/main.rs
index 98d6d9b4..c35aa2bd 100644
--- a/core/invehicle-digital-twin/src/main.rs
+++ b/core/invehicle-digital-twin/src/main.rs
@@ -5,16 +5,14 @@
// Module references behind feature flags. Add any necessary module references here.
// Start: Module references.
-// Add a new feature to all() so the use statement is active for the feature.
-// ex. #[cfg(all(feature = "feature_1", feature = "feature_2"))]
-#[cfg(all(feature = "managed_subscribe"))]
-use common::grpc_interceptor::GrpcInterceptorLayer;
-
#[cfg(feature = "managed_subscribe")]
use managed_subscribe::managed_subscribe_module::ManagedSubscribeModule;
// End: Module references.
+#[allow(unused_imports)]
+use common::grpc_interceptor::GrpcInterceptorLayer;
+
use common::grpc_server::GrpcServer;
use core_protobuf_data_access::chariott::service_discovery::core::v1::service_registry_client::ServiceRegistryClient;
use core_protobuf_data_access::chariott::service_discovery::core::v1::{
diff --git a/devops/cg/license_url_to_type.json b/devops/cg/license_url_to_type.json
new file mode 100644
index 00000000..a4f02904
--- /dev/null
+++ b/devops/cg/license_url_to_type.json
@@ -0,0 +1,5 @@
+{
+ "https://raw.githubusercontent.com/moq/moq4/main/License.txt": "BSD 3-Clause",
+ "https://www.nuget.org/packages/NUnit/3.13.3/License": "MIT",
+ "https://www.nuget.org/packages/NUnit.Analyzers/3.3.0/License": "MIT"
+}
\ No newline at end of file
diff --git a/dtdl-parser/.accepted_words.txt b/dtdl-parser/.accepted_words.txt
deleted file mode 100644
index a0e25ad9..00000000
--- a/dtdl-parser/.accepted_words.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-api
-com
-DTDL
-digitaltwins
-dtdl
-en
-github
-https
-javascript
-js
-microsoft
-sdk
diff --git a/dtdl-parser/Cargo.toml b/dtdl-parser/Cargo.toml
deleted file mode 100644
index 1347b654..00000000
--- a/dtdl-parser/Cargo.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) Microsoft Corporation.
-# Licensed under the MIT license.
-# SPDX-License-Identifier: MIT
-
-[package]
-name = "dtdl-parser"
-version = "0.1.0"
-edition = "2021"
-license = "MIT"
-
-[dependencies]
-async-std = { workspace = true, features = ["attributes"] }
-futures = { workspace = true }
-generic-json = { workspace = true, features = ["serde_json-impl"] }
-iref = { workspace = true }
-json-ld = { git = "https://github.com/blast-hardcheese/json-ld", branch = "resolve-issue-40" }
-lazy_static = { workspace = true }
-log = { workspace = true }
-regex = { workspace = true }
-serde_json = { workspace = true }
-strum = { workspace = true }
-strum_macros = { workspace = true }
-
-[lib]
-path = "src/lib.rs"
-crate-type = ["lib"]
\ No newline at end of file
diff --git a/dtdl-parser/README.md b/dtdl-parser/README.md
deleted file mode 100644
index 545000de..00000000
--- a/dtdl-parser/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# DTDL Parser
-
-## Overview
-
-This is a Rust DTDL Parser, based on the JavaScript DTDL Parser's [code](https://github.com/Azure/azure-sdk-for-js/tree/%40azure/dtdl-parser_1.0.0-beta.2/sdk/digitaltwins/dtdl-parser)
-and [API](https://learn.microsoft.com/en-us/javascript/api/@azure/dtdl-parser). Currently, the Rust DTDL Parser only provides a subset of the functionality of the JavaScript DTDL Parser.
diff --git a/dtdl-parser/dtdl/samples/building.json b/dtdl-parser/dtdl/samples/building.json
deleted file mode 100644
index 500bc7ed..00000000
--- a/dtdl-parser/dtdl/samples/building.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "@id": "dtmi:com:example:Building;1",
- "@type": "Interface",
- "displayName": "Building",
- "contents": [
- {
- "@type": "Property",
- "name": "name",
- "schema": "string",
- "writable": true
- },
- {
- "@type": "Relationship",
- "name": "contains",
- "target": "dtmi:com:example:Room;1"
- }
- ],
- "@context": "dtmi:dtdl:context;3"
-}
diff --git a/dtdl-parser/dtdl/samples/demo_resources.json b/dtdl-parser/dtdl/samples/demo_resources.json
deleted file mode 100644
index 9f401c55..00000000
--- a/dtdl-parser/dtdl/samples/demo_resources.json
+++ /dev/null
@@ -1,42 +0,0 @@
-[
- {
- "@context": ["dtmi:dtdl:context;2", "dtmi:sdv:context;2"],
- "@type": "Interface",
- "@id": "dtmi:sdv:Vehicle:Cabin:HVAC;1",
- "contents": [
- {
- "@type": ["Property", "Temperature", "RemotelyAccessible"],
- "@id": "dtmi:sdv:Vehicle:Cabin:HVAC:AmbientAirTemperature;1",
- "name": "Cabin_AmbientAirTemperature",
- "description": "The immediate surroundings air temperature (in Fahrenheit).",
- "schema": "double",
- "unit": "degreeFahrenheit",
- "remote_access": [
- {
- "@type": "Endpoint",
- "uri": "http://[::1]:40010",
- "operations": [ "Get", "Set", "Subscribe", "Unsubscribe" ]
- }
- ]
- },
- {
- "@type": ["Command", "RemotelyAccessible"],
- "@id": "dtmi:sdv:Vehicle:Cabin:HVAC:SendNotification;1",
- "name": "HVAC_send_notification",
- "request": {
- "name": "send_notification",
- "displayName": "send_notification",
- "description": "Send a notification to the HVAC.",
- "schema": "string"
- },
- "remote_access": [
- {
- "@type": "Endpoint",
- "uri": "http://[::1]:40010",
- "operations": [ "Invoke" ]
- }
- ]
- }
- ]
- }
-]
diff --git a/dtdl-parser/dtdl/samples/phone.json b/dtdl-parser/dtdl/samples/phone.json
deleted file mode 100644
index 18c30fc9..00000000
--- a/dtdl-parser/dtdl/samples/phone.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "@id": "dtmi:com:example:Phone;2",
- "@type": "Interface",
- "displayName": "Phone",
- "contents": [
- {
- "@type": "Component",
- "name": "frontCamera",
- "schema": "dtmi:com:example:Camera;3"
- },
- {
- "@type": "Component",
- "name": "backCamera",
- "schema": "dtmi:com:example:Camera;3"
- },
- {
- "@type": "Component",
- "name": "deviceInfo",
- "schema": "dtmi:azure:deviceManagement:DeviceInformation;2"
- }
- ],
- "@context": "dtmi:dtdl:context;3"
-}
diff --git a/dtdl-parser/dtdl/samples/thermostat.json b/dtdl-parser/dtdl/samples/thermostat.json
deleted file mode 100644
index 654fc7e9..00000000
--- a/dtdl-parser/dtdl/samples/thermostat.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "@id": "dtmi:com:example:Thermostat;1",
- "@type": "Interface",
- "displayName": "Thermostat",
- "contents": [
- {
- "@type": "Telemetry",
- "name": "temp",
- "schema": "double"
- },
- {
- "@type": "Property",
- "name": "setPointTemp",
- "writable": true,
- "schema": "double"
- }
- ],
- "@context": "dtmi:dtdl:context;3"
-}
diff --git a/dtdl-parser/src/command_info.rs b/dtdl-parser/src/command_info.rs
deleted file mode 100644
index 9585bad1..00000000
--- a/dtdl-parser/src/command_info.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::command_payload_info::CommandPayloadInfo;
-use crate::content_info::ContentInfo;
-
-/// A command is a method that can be invoked on a digital twin.
-pub trait CommandInfo: ContentInfo {
- /// Returns the request.
- fn request(&self) -> &Option>;
-
- /// Returns the response.
- fn response(&self) -> &Option>;
-}
diff --git a/dtdl-parser/src/command_info_impl.rs b/dtdl-parser/src/command_info_impl.rs
deleted file mode 100644
index 5afc6093..00000000
--- a/dtdl-parser/src/command_info_impl.rs
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::command_info::CommandInfo;
-use crate::command_payload_info::CommandPayloadInfo;
-use crate::content_info::ContentInfo;
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-use crate::entity_kind::EntityKind;
-use crate::named_entity_info::NamedEntityInfo;
-
-pub struct CommandInfoImpl {
- // EntityInfo
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- description: Option,
- display_name: Option,
- undefined_properties: HashMap,
-
- // NamedEntityInfo
- name: Option,
-
- // CommandInfo
- request: Option>,
- response: Option>,
-}
-
-impl CommandInfoImpl {
- /// Returns a new CommandInfoImpl.
- ///
- /// # Arguments
- /// * `dtdl_version` - The DTDL version used to define the command.
- /// * `id` - The identifier.
- /// * `child_of` - The identifier of the parent element in which this command is defined.
- /// * `defined_in` - The identifier of the partition in which this command is defined.
- /// * `name` - The name.
- /// * `request` - The request.
- /// * `response` - The response.
- pub fn new(
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- name: Option,
- request: Option>,
- response: Option>,
- ) -> Self {
- Self {
- dtdl_version,
- id,
- child_of,
- defined_in,
- description: None,
- display_name: None,
- undefined_properties: HashMap::::new(),
- name,
- request,
- response,
- }
- }
-
- /// Add an undefined property.
- /// # Arguments
- /// * `key` - The property's name.
- /// * `value` - The property's value.
- pub fn add_undefined_property(&mut self, key: String, value: Value) {
- self.undefined_properties.insert(key, value);
- }
-}
-
-impl EntityInfo for CommandInfoImpl {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32 {
- self.dtdl_version
- }
-
- /// Returns the identifier.
- fn id(&self) -> &Dtmi {
- &self.id
- }
-
- /// Returns the kind of entity.
- fn entity_kind(&self) -> EntityKind {
- EntityKind::Command
- }
-
- /// Returns the parent's identifier.
- fn child_of(&self) -> &Option {
- &self.child_of
- }
-
- /// Returns the enclosing partition's identifier.
- fn defined_in(&self) -> &Option {
- &self.defined_in
- }
-
- // Returns the description for this entity.
- fn description(&self) -> &Option {
- &self.description
- }
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option {
- &self.display_name
- }
-
- /// Returns all undefined properties.
- fn undefined_properties(&self) -> &HashMap {
- &self.undefined_properties
- }
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
-impl NamedEntityInfo for CommandInfoImpl {
- /// Returns the name.
- fn name(&self) -> &Option {
- &self.name
- }
-}
-
-impl ContentInfo for CommandInfoImpl {}
-
-impl CommandInfo for CommandInfoImpl {
- /// Returns the request.
- fn request(&self) -> &Option> {
- &self.request
- }
-
- /// Returns the response.
- fn response(&self) -> &Option> {
- &self.response
- }
-}
-
-#[cfg(test)]
-mod command_info_impl_tests {
- use super::*;
- use crate::command_payload_info_impl::CommandPayloadInfoImpl;
- use crate::dtmi::{create_dtmi, Dtmi};
- use crate::model_parser::DTDL_VERSION;
- use crate::primitive_schema_info_impl::PrimitiveSchemaInfoImpl;
- use serde_json;
-
- #[test]
- fn new_command_info_impl_test() -> Result<(), String> {
- let id_result: Option =
- create_dtmi("dtmi:com.example:command:HVAC:send_notification;1");
- assert!(id_result.is_some());
- let id = id_result.unwrap();
-
- let child_of_result: Option = create_dtmi("dtmi:com:example:HVAC;1.0");
- assert!(child_of_result.is_some());
- let child_of = child_of_result.unwrap();
-
- let defined_in_result: Option = create_dtmi("dtmi:com:example;1.0");
- assert!(defined_in_result.is_some());
- let defined_in = defined_in_result.unwrap();
-
- let first_propery_value: Value = serde_json::from_str("{\"first\": \"this\"}").unwrap();
- let second_propery_value: Value = serde_json::from_str("{\"second\": \"that\"}").unwrap();
-
- let string_schema_info_id: Option = create_dtmi("dtmi:dtdl:class:String;2");
- assert!(string_schema_info_id.is_some());
- let string_schema_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- string_schema_info_id.unwrap(),
- None,
- None,
- EntityKind::String,
- ));
-
- let integer_schema_info_id: Option = create_dtmi("dtmi:dtdl:class:Integer;2");
- assert!(integer_schema_info_id.is_some());
- let integer_schema_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- integer_schema_info_id.unwrap(),
- None,
- None,
- EntityKind::Integer,
- ));
-
- let request_id: Option = create_dtmi("dtmi:com:example:send_notification:request:1");
- assert!(request_id.is_some());
- let request = Box::new(CommandPayloadInfoImpl::new(
- DTDL_VERSION,
- request_id.unwrap(),
- None,
- None,
- None,
- Some(string_schema_info),
- ));
-
- let response_id: Option =
- create_dtmi("dtmi:com:example:send_notification:response:1");
- assert!(response_id.is_some());
- let response = Box::new(CommandPayloadInfoImpl::new(
- DTDL_VERSION,
- response_id.unwrap(),
- None,
- None,
- None,
- Some(integer_schema_info),
- ));
-
- let mut command_info = CommandInfoImpl::new(
- DTDL_VERSION,
- id.clone(),
- Some(child_of.clone()),
- Some(defined_in.clone()),
- Some(String::from("one")),
- Some(request),
- Some(response),
- );
- command_info.add_undefined_property(String::from("first"), first_propery_value.clone());
- command_info.add_undefined_property(String::from("second"), second_propery_value.clone());
-
- assert_eq!(command_info.dtdl_version(), 2);
- assert_eq!(command_info.id(), &id);
- assert!(command_info.child_of().is_some());
- assert_eq!(command_info.child_of().clone().unwrap(), child_of);
- assert!(command_info.defined_in().is_some());
- assert_eq!(command_info.defined_in().clone().unwrap(), defined_in);
- assert_eq!(command_info.entity_kind(), EntityKind::Command);
- assert_eq!(command_info.undefined_properties().len(), 2);
- assert_eq!(
- command_info.undefined_properties().get("first").unwrap().clone(),
- first_propery_value
- );
- assert_eq!(
- command_info.undefined_properties().get("second").unwrap().clone(),
- second_propery_value
- );
-
- match command_info.name() {
- Some(name) => assert_eq!(name, "one"),
- None => return Err(String::from("name has not been set")),
- }
-
- match command_info.request() {
- Some(request) => {
- assert_eq!(request.entity_kind(), EntityKind::CommandPayload);
- match request.schema() {
- Some(schema) => assert_eq!(schema.entity_kind(), EntityKind::String),
- None => return Err(String::from("request's schema has not been set")),
- }
- }
- None => return Err(String::from("request has not been set")),
- }
-
- match command_info.response() {
- Some(response) => {
- assert_eq!(response.entity_kind(), EntityKind::CommandPayload);
- match response.schema() {
- Some(schema) => assert_eq!(schema.entity_kind(), EntityKind::Integer),
- None => return Err(String::from("response's schema has not been set")),
- }
- }
- None => return Err(String::from("request has not been set")),
- }
-
- Ok(())
- }
-}
diff --git a/dtdl-parser/src/command_payload_info.rs b/dtdl-parser/src/command_payload_info.rs
deleted file mode 100644
index 7e1ab1bc..00000000
--- a/dtdl-parser/src/command_payload_info.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::schema_field_info::SchemaFieldInfo;
-
-/// A command payload specifies the inputs and outputs for a command.
-pub trait CommandPayloadInfo: SchemaFieldInfo {}
diff --git a/dtdl-parser/src/command_payload_info_impl.rs b/dtdl-parser/src/command_payload_info_impl.rs
deleted file mode 100644
index bef167ec..00000000
--- a/dtdl-parser/src/command_payload_info_impl.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::command_payload_info::CommandPayloadInfo;
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-use crate::entity_kind::EntityKind;
-use crate::named_entity_info::NamedEntityInfo;
-use crate::schema_field_info::SchemaFieldInfo;
-use crate::schema_info::SchemaInfo;
-
-pub struct CommandPayloadInfoImpl {
- // EntityInfo
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- description: Option,
- display_name: Option,
- undefined_properties: HashMap,
-
- // NamedEntityInfo
- name: Option,
-
- // SchemaFieldInfo
- schema: Option>,
-}
-
-impl CommandPayloadInfoImpl {
- /// Returns a new CommandPayloadInfoImpl.
- ///
- /// # Arguments
- /// * `dtdl_version` - The DTDL version used to define the command payload.
- /// * `id` - The identifier.
- /// * `child_of` - The identifier of the parent element in which this command payload is defined.
- /// * `defined_in` - The identifier of the partition in which this command payload is defined.
- /// * `name` - The name.
- /// * `schema` - The schema.
- pub fn new(
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- name: Option,
- schema: Option>,
- ) -> Self {
- Self {
- dtdl_version,
- id,
- child_of,
- defined_in,
- description: None,
- display_name: None,
- undefined_properties: HashMap::::new(),
- name,
- schema,
- }
- }
-
- /// Add an undefined property.
- /// # Arguments
- /// * `key` - The property's name.
- /// * `value` - The property's value.
- pub fn add_undefined_property(&mut self, key: String, value: Value) {
- self.undefined_properties.insert(key, value);
- }
-}
-
-impl EntityInfo for CommandPayloadInfoImpl {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32 {
- self.dtdl_version
- }
-
- /// Returns the identifier.
- fn id(&self) -> &Dtmi {
- &self.id
- }
-
- /// Returns the kind of entity.
- fn entity_kind(&self) -> EntityKind {
- EntityKind::CommandPayload
- }
-
- /// Returns the parent's identifier.
- fn child_of(&self) -> &Option {
- &self.child_of
- }
-
- /// Returns the enclosing partition's identifider.
- fn defined_in(&self) -> &Option {
- &self.defined_in
- }
-
- // Returns the description for this entity.
- fn description(&self) -> &Option {
- &self.description
- }
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option {
- &self.display_name
- }
-
- /// Returns all undefined properties.
- fn undefined_properties(&self) -> &HashMap {
- &self.undefined_properties
- }
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
-impl NamedEntityInfo for CommandPayloadInfoImpl {
- /// Returns the name.
- fn name(&self) -> &Option {
- &self.name
- }
-}
-
-impl SchemaFieldInfo for CommandPayloadInfoImpl {
- /// Returns the schema.
- fn schema(&self) -> &Option> {
- &self.schema
- }
-}
-
-impl CommandPayloadInfo for CommandPayloadInfoImpl {}
-
-#[cfg(test)]
-mod command_payload_info_impl_tests {
- use super::*;
- use crate::dtmi::{create_dtmi, Dtmi};
- use crate::model_parser::DTDL_VERSION;
- use crate::primitive_schema_info_impl::PrimitiveSchemaInfoImpl;
- use serde_json;
-
- #[test]
- fn new_command_payload_info_impl_test() -> Result<(), String> {
- let id_result: Option = create_dtmi("dtmi:com:example:send_notification:request;1.0");
- assert!(id_result.is_some());
- let id = id_result.unwrap();
-
- let child_of_result: Option = create_dtmi("dtmi:com:example:HVAC;1.0");
- assert!(child_of_result.is_some());
- let child_of = child_of_result.unwrap();
-
- let defined_in_result: Option = create_dtmi("dtmi:com:example;1.0");
- assert!(defined_in_result.is_some());
- let defined_in = defined_in_result.unwrap();
-
- let first_propery_value: Value = serde_json::from_str("{\"first\": \"this\"}").unwrap();
- let second_propery_value: Value = serde_json::from_str("{\"second\": \"that\"}").unwrap();
-
- let schema_info_id: Option = create_dtmi("dtmi:dtdl:class:String;2");
- assert!(schema_info_id.is_some());
-
- let boxed_schema_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- schema_info_id.unwrap(),
- None,
- None,
- EntityKind::String,
- ));
-
- let mut command_payload_info = CommandPayloadInfoImpl::new(
- DTDL_VERSION,
- id.clone(),
- Some(child_of.clone()),
- Some(defined_in.clone()),
- Some(String::from("one")),
- Some(boxed_schema_info),
- );
- command_payload_info
- .add_undefined_property(String::from("first"), first_propery_value.clone());
- command_payload_info
- .add_undefined_property(String::from("second"), second_propery_value.clone());
-
- assert_eq!(command_payload_info.dtdl_version(), DTDL_VERSION);
- assert_eq!(command_payload_info.id(), &id);
- assert!(command_payload_info.child_of().is_some());
- assert_eq!(command_payload_info.child_of().clone().unwrap(), child_of);
- assert!(command_payload_info.defined_in().is_some());
- assert_eq!(command_payload_info.defined_in().clone().unwrap(), defined_in);
- assert_eq!(command_payload_info.entity_kind(), EntityKind::CommandPayload);
- assert!(command_payload_info.schema().is_some());
- match command_payload_info.schema() {
- Some(schema) => assert_eq!(schema.entity_kind(), EntityKind::String),
- None => return Err(String::from("schema has not been set")),
- }
-
- assert_eq!(command_payload_info.undefined_properties().len(), 2);
- assert_eq!(
- command_payload_info.undefined_properties().get("first").unwrap().clone(),
- first_propery_value
- );
- assert_eq!(
- command_payload_info.undefined_properties().get("second").unwrap().clone(),
- second_propery_value
- );
-
- match command_payload_info.name() {
- Some(name) => assert_eq!(name, "one"),
- None => return Err(String::from("name has not been set")),
- }
-
- Ok(())
- }
-}
diff --git a/dtdl-parser/src/complex_schema_info.rs b/dtdl-parser/src/complex_schema_info.rs
deleted file mode 100644
index 07c36870..00000000
--- a/dtdl-parser/src/complex_schema_info.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::schema_info::SchemaInfo;
-
-/// A complex schema is the base trait for all complex schemas, like object, map and array.
-pub trait ComplexSchemaInfo: SchemaInfo {}
diff --git a/dtdl-parser/src/component_info.rs b/dtdl-parser/src/component_info.rs
deleted file mode 100644
index 09469211..00000000
--- a/dtdl-parser/src/component_info.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::content_info::ContentInfo;
-use crate::interface_info::InterfaceInfo;
-
-/// A component specifies a reference to an interface. It allows interfaces to contain other interfaces.
-pub trait ComponentInfo: ContentInfo {
- /// Returns the interface, the component uses the term "schema" to refer to it.
- fn schema(&self) -> &Option>;
-}
diff --git a/dtdl-parser/src/component_info_impl.rs b/dtdl-parser/src/component_info_impl.rs
deleted file mode 100644
index cb3fb200..00000000
--- a/dtdl-parser/src/component_info_impl.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::component_info::ComponentInfo;
-use crate::content_info::ContentInfo;
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-use crate::entity_kind::EntityKind;
-use crate::interface_info::InterfaceInfo;
-use crate::named_entity_info::NamedEntityInfo;
-
-pub struct ComponentInfoImpl {
- // EntityInfo
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- description: Option,
- display_name: Option,
- undefined_properties: HashMap,
-
- // NamedEntityInfo
- name: Option,
-
- // ComponentInfo
- schema: Option>,
-}
-
-impl ComponentInfoImpl {
- /// Returns a new ComponentInfoImpl.
- ///
- /// # Arguments
- /// * `dtdl_version` - The DTDL version used to define the component.
- /// * `id` - The identifier.
- /// * `child_of` - The identifier of the parent element in which this component is defined.
- /// * `defined_in` - The identifier of the partition in which this component is defined.
- /// * `name` - The name.
- /// * `schema` - The interface.
- pub fn new(
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- name: Option,
- schema: Option>,
- ) -> Self {
- Self {
- dtdl_version,
- id,
- child_of,
- defined_in,
- description: None,
- display_name: None,
- undefined_properties: HashMap::::new(),
- name,
- schema,
- }
- }
-
- /// Add an undefined property.
- /// # Arguments
- /// * `key` - The property's name.
- /// * `value` - The property's value.
- pub fn add_undefined_property(&mut self, key: String, value: Value) {
- self.undefined_properties.insert(key, value);
- }
-}
-
-impl EntityInfo for ComponentInfoImpl {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32 {
- self.dtdl_version
- }
-
- /// Returns the identifier.
- fn id(&self) -> &Dtmi {
- &self.id
- }
-
- /// Returns the kind of entity.
- fn entity_kind(&self) -> EntityKind {
- EntityKind::Component
- }
-
- /// Returns the parent's identifier.
- fn child_of(&self) -> &Option {
- &self.child_of
- }
-
- /// Returns the enclosing partition's identifier.
- fn defined_in(&self) -> &Option {
- &self.defined_in
- }
-
- // Returns the description for this entity.
- fn description(&self) -> &Option {
- &self.description
- }
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option {
- &self.display_name
- }
-
- /// Returns all undefined properties.
- fn undefined_properties(&self) -> &HashMap {
- &self.undefined_properties
- }
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
-impl NamedEntityInfo for ComponentInfoImpl {
- /// Returns the name.
- fn name(&self) -> &Option {
- &self.name
- }
-}
-
-impl ContentInfo for ComponentInfoImpl {}
-
-impl ComponentInfo for ComponentInfoImpl {
- /// Returns the interface.
- fn schema(&self) -> &Option> {
- &self.schema
- }
-}
-
-#[cfg(test)]
-mod component_info_impl_tests {
- use super::*;
- use crate::dtmi::{create_dtmi, Dtmi};
- use crate::interface_info_impl::InterfaceInfoImpl;
- use crate::model_parser::DTDL_VERSION;
- use serde_json;
-
- #[test]
- fn new_component_info_impl_test() -> Result<(), String> {
- let id_result: Option = create_dtmi("dtmi:com:example:Thermostat;1.0");
- assert!(id_result.is_some());
- let id = id_result.unwrap();
-
- let child_of_result: Option = create_dtmi("dtmi:com:example:Cabin;1.0");
- assert!(child_of_result.is_some());
- let child_of = child_of_result.unwrap();
-
- let defined_in_result: Option = create_dtmi("dtmi:com:example:Something;1.0");
- assert!(defined_in_result.is_some());
- let defined_in = defined_in_result.unwrap();
-
- let first_propery_value: Value = serde_json::from_str("{\"first\": \"this\"}").unwrap();
- let second_propery_value: Value = serde_json::from_str("{\"second\": \"that\"}").unwrap();
-
- let schema_info_id: Option = create_dtmi("dtmi:dtdl:class:String;2");
- assert!(schema_info_id.is_some());
-
- let boxed_interface_info =
- Box::new(InterfaceInfoImpl::new(DTDL_VERSION, schema_info_id.unwrap(), None, None));
-
- let mut component_info = ComponentInfoImpl::new(
- DTDL_VERSION,
- id.clone(),
- Some(child_of.clone()),
- Some(defined_in.clone()),
- Some(String::from("one")),
- Some(boxed_interface_info),
- );
- component_info.add_undefined_property(String::from("first"), first_propery_value.clone());
- component_info.add_undefined_property(String::from("second"), second_propery_value.clone());
-
- assert_eq!(component_info.dtdl_version(), 2);
- assert_eq!(component_info.id(), &id);
- assert!(component_info.child_of().is_some());
- assert_eq!(component_info.child_of().clone().unwrap(), child_of);
- assert!(component_info.defined_in().is_some());
- assert_eq!(component_info.defined_in().clone().unwrap(), defined_in);
- assert_eq!(component_info.entity_kind(), EntityKind::Component);
- assert_eq!(component_info.undefined_properties().len(), 2);
- assert_eq!(
- component_info.undefined_properties().get("first").unwrap().clone(),
- first_propery_value
- );
- assert_eq!(
- component_info.undefined_properties().get("second").unwrap().clone(),
- second_propery_value
- );
-
- match component_info.name() {
- Some(name) => assert_eq!(name, "one"),
- None => return Err(String::from("name has not been set")),
- }
-
- match component_info.schema() {
- Some(schema) => assert_eq!(schema.entity_kind(), EntityKind::Interface),
- None => return Err(String::from("schema has not been set")),
- }
-
- Ok(())
- }
-}
diff --git a/dtdl-parser/src/content_info.rs b/dtdl-parser/src/content_info.rs
deleted file mode 100644
index 21a030da..00000000
--- a/dtdl-parser/src/content_info.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::named_entity_info::NamedEntityInfo;
-
-/// An abstract trait that represents entites that have content.
-pub trait ContentInfo: NamedEntityInfo {}
diff --git a/dtdl-parser/src/dtmi.rs b/dtdl-parser/src/dtmi.rs
deleted file mode 100644
index 9bc6f23d..00000000
--- a/dtdl-parser/src/dtmi.rs
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use iref::Iri;
-use log::warn;
-use regex::Regex;
-use std::fmt;
-
-lazy_static! {
- pub static ref DTMI_REGEX: Regex =
- Regex::new(r"^dtmi:[^;]+(;[1-9][0-9]*(\.[0-9][1-9]*)?)?(#[^ ]*)?$").unwrap();
-}
-
-/// Digital Twin Model Identifier (DTMI).
-#[derive(Debug, Default, Clone, Hash, Eq, PartialEq)]
-pub struct Dtmi {
- value: String,
- major_version: Option,
- minor_version: Option,
- versionless: String,
- labels: Vec,
- absolute_path: String,
- fragment: String,
-}
-
-impl Dtmi {
- /// Returns a new DTMI instance.
- ///
- /// # Arguments
- /// * `value` - The string representation of the DTMI.
- pub fn new(value: &str) -> Result {
- let new_iri_result = Iri::new(value);
- if new_iri_result.is_err() {
- return Err(format!("The value '{value}' does not represent a valid IRI"));
- }
- let iri = new_iri_result.unwrap();
-
- let mut major_version: Option = None;
- let mut minor_version: Option = None;
- let absolute_path: String;
-
- let iri_path_parts: Vec<&str> = iri.path().into_str().split(';').collect();
- if iri_path_parts.len() == 1 {
- // no version
- absolute_path = String::from(iri_path_parts[0]);
- } else if iri_path_parts.len() == 2 {
- absolute_path = String::from(iri_path_parts[0]);
- let version_parts: Vec<&str> = iri_path_parts[1].split('.').collect();
- if version_parts.len() == 1 {
- // no minor version number
- if let Ok(value) = version_parts[0].parse::() {
- major_version = Some(value)
- }
- } else if version_parts.len() == 2 {
- if let Ok(value) = version_parts[0].parse::() {
- major_version = Some(value)
- }
- if let Ok(value) = version_parts[1].parse::() {
- minor_version = Some(value)
- }
- } else {
- return Err(format!("The value '{value}' has an invalid version"));
- }
- } else {
- return Err(format!("The value '{value}' represents an invalid DTMI"));
- }
-
- let versionless: String = format!("dtmi:{absolute_path}");
-
- let labels: Vec = absolute_path.split(':').map(Into::into).collect();
-
- let fragment = match iri.fragment() {
- Some(fragment) => String::from(fragment.as_str()),
- None => String::new(),
- };
-
- Ok(Self {
- value: String::from(value),
- major_version,
- minor_version,
- versionless,
- labels,
- absolute_path,
- fragment,
- })
- }
-
- /// Gets the string representation of the DTMI.
- pub fn value(&self) -> &str {
- &self.value
- }
-
- /// Gets the major version of the DTMI.
- pub fn major_version(&self) -> &Option {
- &self.major_version
- }
-
- /// Gets the minor version of the DTMI.
- pub fn minor_version(&self) -> &Option {
- &self.minor_version
- }
-
- /// Gets the major and minor version of the DTMI.
- pub fn complete_version(&self) -> f64 {
- let major_version: f64 = match self.major_version {
- Some(value) => value.into(),
- None => 0.0,
- };
-
- let minor_version: f64 = match self.minor_version {
- Some(value) => value.into(),
- None => 0.0,
- };
-
- major_version + minor_version * 0.000001
- }
-
- /// Gets the portion of the DTMI that preceeds the version number.
- pub fn versionless(&self) -> &str {
- &self.versionless
- }
-
- /// Gets the sequence of labels in the path portion of the DTMI.
- pub fn labels(&self) -> &Vec {
- &self.labels
- }
-
- /// Gets the absolute path of the DTMI.
- pub fn absolute_path(&self) -> &str {
- &self.absolute_path
- }
-
- /// Gets the name of the DTMI's fragment, which is the empty string if there is no fragment.
- pub fn fragment(&self) -> &str {
- &self.fragment
- }
-}
-
-impl fmt::Display for Dtmi {
- /// Format support for DTMI.
- ///
- /// # Arguments
- /// * `f` - The associated formatter.
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.value())
- }
-}
-
-/// Create a new DTMI instance.
-///
-/// # Arguments
-/// * `value` - The IRI to copy from.
-pub fn create_dtmi(value: &str) -> Option {
- if !DTMI_REGEX.is_match(value) {
- warn!("The value '{value}' does not represent a valid DTMI");
- return None;
- }
-
- let new_dtmi_result = Dtmi::new(value);
- if let Err(error) = new_dtmi_result {
- warn!("{error}");
- return None;
- }
-
- Some(new_dtmi_result.unwrap())
-}
-
-#[cfg(test)]
-mod dmti_tests {
- use super::*;
-
- #[test]
- fn new_dtmi_test() {
- let mut new_dtmi_result = Dtmi::new("dtmi:com:example:Thermostat;1.234#some-fragment");
- assert!(new_dtmi_result.is_ok());
- let mut dtmi: Dtmi = new_dtmi_result.unwrap();
- assert!(dtmi.major_version().is_some());
- assert_eq!(dtmi.major_version().unwrap(), 1);
- assert!(dtmi.minor_version().is_some());
- assert_eq!(dtmi.minor_version().unwrap(), 234);
- assert_eq!(dtmi.complete_version(), 1.000234);
- assert_eq!(dtmi.versionless(), "dtmi:com:example:Thermostat");
- assert_eq!(dtmi.labels().len(), 3);
- assert_eq!(dtmi.labels()[0], "com");
- assert_eq!(dtmi.labels()[1], "example");
- assert_eq!(dtmi.labels()[2], "Thermostat");
- assert_eq!(dtmi.absolute_path, "com:example:Thermostat");
- assert_eq!(dtmi.fragment(), "some-fragment");
- assert_eq!(format!("{dtmi}"), "dtmi:com:example:Thermostat;1.234#some-fragment");
-
- new_dtmi_result = Dtmi::new("dtmi:com:example:Thermostat;1.234#");
- assert!(new_dtmi_result.is_ok());
- dtmi = new_dtmi_result.unwrap();
- assert_eq!(dtmi.fragment(), "");
- assert_eq!(format!("{dtmi}"), "dtmi:com:example:Thermostat;1.234#");
- }
-
- #[test]
- fn create_dtmi_test() {
- let create_dtmi_result: Option = create_dtmi("dtmi:com:example:Thermostat;1.234567");
- assert!(create_dtmi_result.is_some());
- let dtmi = create_dtmi_result.unwrap();
- assert!(dtmi.major_version().is_some());
- assert!(dtmi.major_version().unwrap() == 1);
- assert!(dtmi.minor_version().is_some());
- assert!(dtmi.minor_version().unwrap() == 234567);
- assert_eq!(dtmi.complete_version(), 1.234567);
- assert_eq!(dtmi.versionless(), "dtmi:com:example:Thermostat");
- assert_eq!(dtmi.labels().len(), 3);
- assert_eq!(dtmi.labels()[0], "com");
- assert_eq!(dtmi.labels()[1], "example");
- assert_eq!(dtmi.labels()[2], "Thermostat");
- assert_eq!(dtmi.absolute_path, "com:example:Thermostat");
- }
-
- #[test]
- fn bad_create_dtmi_test() {
- let mut create_dtmi_result: Option =
- create_dtmi("whatever:com:example:Thermostat;1.234567");
- assert!(create_dtmi_result.is_none());
-
- create_dtmi_result = create_dtmi("dtmi:com:example:Thermostat;1.2.3");
- assert!(create_dtmi_result.is_none());
-
- create_dtmi_result = create_dtmi("dtmi:;1.2");
- assert!(create_dtmi_result.is_none());
- }
-
- #[test]
- fn eq_dtmi_test() {
- let first_create_dtmi_result: Option =
- create_dtmi("dtmi:com:example:Thermostat;1.234567");
- assert!(first_create_dtmi_result.is_some());
- let first_dtmi = first_create_dtmi_result.unwrap();
-
- let second_create_dtmi_result: Option =
- create_dtmi("dtmi:com:example:Thermostat;1.234567");
- assert!(second_create_dtmi_result.is_some());
- let second_dtmi = second_create_dtmi_result.unwrap();
-
- let third_create_dtmi_result: Option =
- create_dtmi("dtmi:com:example:Barometer;2.987");
- assert!(third_create_dtmi_result.is_some());
- let third_dtmi = third_create_dtmi_result.unwrap();
-
- assert_eq!(first_dtmi, second_dtmi);
- assert!(first_dtmi != third_dtmi);
- }
-}
diff --git a/dtdl-parser/src/entity_info.rs b/dtdl-parser/src/entity_info.rs
deleted file mode 100644
index ff21053f..00000000
--- a/dtdl-parser/src/entity_info.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::dtmi::Dtmi;
-use crate::entity_kind::EntityKind;
-
-/// A digital twin model consists of building blocks known as entities.
-/// EntityInfo is the base trait for all of the digital twin model building blocks.
-pub trait EntityInfo: Any {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32;
-
- /// Returns the identifier of the DTDL element that corresponds to this object.
- fn id(&self) -> &Dtmi;
-
- /// Returns the kind of Entity, meaning the concrete DTDL type assigned to the corresponding element in the model.
- fn entity_kind(&self) -> EntityKind;
-
- /// Returns the identifier of the parent DTDL element in which this element is defined.
- fn child_of(&self) -> &Option;
-
- /// Returns the identifier of the partition DTDL element in which this element is defined.
- fn defined_in(&self) -> &Option;
-
- // Returns the description for this entity.
- fn description(&self) -> &Option;
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option;
-
- /// Returns any undefined properties of the DTDL element that corresponds to this object.
- fn undefined_properties(&self) -> &HashMap;
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any;
-}
diff --git a/dtdl-parser/src/entity_kind.rs b/dtdl-parser/src/entity_kind.rs
deleted file mode 100644
index 2ff71022..00000000
--- a/dtdl-parser/src/entity_kind.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use strum_macros::Display;
-use strum_macros::EnumIter;
-use strum_macros::EnumString;
-
-/// Indicates the kind of Entity, meaning the concrete DTDL type assigned to the corresponding element in the model.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, Display)]
-pub enum EntityKind {
- #[strum(serialize = "dtmi:dtdl:class:Array;2")]
- Array,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:boolean;2")]
- Boolean,
-
- #[strum(serialize = "dtmi:dtdl:class:Command;2")]
- Command,
-
- #[strum(serialize = "dtmi:dtdl:class:CommandPayload;2")]
- CommandPayload,
-
- #[strum(serialize = "dtmi:dtdl:class:CommandType;2")]
- CommandType,
-
- #[strum(serialize = "dtmi:dtdl:class:Component;2")]
- Component,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:date;2")]
- Date,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:dateTime;2")]
- DateTime,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:double;2")]
- Double,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:duration;2")]
- Duration,
-
- #[strum(serialize = "dtmi:dtdl:class:Enum;2")]
- Enum,
-
- #[strum(serialize = "dtmi:dtdl:class:EnumValue;2")]
- EnumValue,
-
- #[strum(serialize = "dtmi:dtdl:class:Field;2")]
- Field,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:float;2")]
- Float,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:integer;2")]
- Integer,
-
- #[strum(serialize = "dtmi:dtdl:class:Interface;2")]
- Interface,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:long;2")]
- Long,
-
- #[strum(serialize = "dtmi:dtdl:class:Map;2")]
- Map,
-
- #[strum(serialize = "dtmi:dtdl:class:MapKey;2")]
- MapKey,
-
- #[strum(serialize = "dtmi:dtdl:class:MapValue;2")]
- MapValue,
-
- #[strum(serialize = "dtmi:dtdl:class:Object;2")]
- Object,
-
- #[strum(serialize = "dtmi:dtdl:class:Property;2")]
- Property,
-
- #[strum(serialize = "dtmi:dtdl:class:Relationship;2")]
- Relationship,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:string;2")]
- String,
-
- #[strum(serialize = "dtmi:dtdl:class:Telemetry;2")]
- Telemetry,
-
- #[strum(serialize = "dtmi:dtdl:instance:Schema:time;2")]
- Time,
-
- #[strum(serialize = "dtmi:dtdl:class:Unit;2")]
- Unit,
-
- #[strum(serialize = "dtmi:dtdl:class:UnitAttribute;2")]
- UnitAttribute,
-
- #[strum(serialize = "dtmi:dtdl:class:CommandRequest;2")]
- CommandRequest,
-
- #[strum(serialize = "dtmi:dtdl:class:CommandResponse;2")]
- CommandResponse,
-
- #[strum(serialize = "dtmi:dtdl:class:LatentType;2")]
- LatentType,
-
- #[strum(serialize = "dtmi:dtdl:class:NamedLatentType;2")]
- NamedLatentType,
-
- #[strum(serialize = "dtmi:dtdl:class:Reference;2")]
- Reference,
-}
diff --git a/dtdl-parser/src/field_info.rs b/dtdl-parser/src/field_info.rs
deleted file mode 100644
index a5e628ef..00000000
--- a/dtdl-parser/src/field_info.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::schema_field_info::SchemaFieldInfo;
-
-/// Specifies a field.
-pub trait FieldInfo: SchemaFieldInfo {}
diff --git a/dtdl-parser/src/field_info_impl.rs b/dtdl-parser/src/field_info_impl.rs
deleted file mode 100644
index c9b4bb75..00000000
--- a/dtdl-parser/src/field_info_impl.rs
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-use crate::entity_kind::EntityKind;
-use crate::field_info::FieldInfo;
-use crate::named_entity_info::NamedEntityInfo;
-use crate::schema_field_info::SchemaFieldInfo;
-use crate::schema_info::SchemaInfo;
-
-pub struct FieldInfoImpl {
- // EntityInfo
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- description: Option,
- display_name: Option,
- undefined_properties: HashMap,
-
- // NamedEntityInfo
- name: Option,
-
- // SchemaFieldInfo
- schema: Option>,
-}
-
-impl FieldInfoImpl {
- /// Returns a new FieldInfoImpl.
- ///
- /// # Arguments
- /// * `dtdl_version` - The DTDL version used to define the field.
- /// * `id` - The identifier..
- /// * `child_of` - The identifier of the parent element in which this field is defined.
- /// * `defined_in` - The identifier of the partition in which this field is defined.
- /// * `name` - The name.
- /// * `schema` - The schema.
- pub fn new(
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- name: Option,
- schema: Option>,
- ) -> Self {
- Self {
- dtdl_version,
- id,
- child_of,
- defined_in,
- description: None,
- display_name: None,
- undefined_properties: HashMap::::new(),
- name,
- schema,
- }
- }
-
- /// Set the display name.
- ///
- /// # Arguments
- /// `display_name` - The new display name.
- pub fn set_display_name(&mut self, display_name: Option) {
- self.display_name = display_name;
- }
-
- /// Add an undefined property.
- /// # Arguments
- /// * `key` - The property's name.
- /// * `value` - The property's value.
- pub fn add_undefined_property(&mut self, key: String, value: Value) {
- self.undefined_properties.insert(key, value);
- }
-}
-
-impl EntityInfo for FieldInfoImpl {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32 {
- self.dtdl_version
- }
-
- /// Returns the identifier.
- fn id(&self) -> &Dtmi {
- &self.id
- }
-
- /// Returns the kind of entity.
- fn entity_kind(&self) -> EntityKind {
- EntityKind::Telemetry
- }
-
- /// Returns the parent's identifier.
- fn child_of(&self) -> &Option {
- &self.child_of
- }
-
- /// Returns the enclosing partition's identifier.
- fn defined_in(&self) -> &Option {
- &self.defined_in
- }
-
- // Returns the description for this entity.
- fn description(&self) -> &Option {
- &self.description
- }
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option {
- &self.display_name
- }
-
- /// Returns all undefined properties.
- fn undefined_properties(&self) -> &HashMap {
- &self.undefined_properties
- }
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
-impl NamedEntityInfo for FieldInfoImpl {
- /// Returns the name of the field.
- fn name(&self) -> &Option {
- &self.name
- }
-}
-
-impl SchemaFieldInfo for FieldInfoImpl {
- /// Returns the schema.
- fn schema(&self) -> &Option> {
- &self.schema
- }
-}
-
-impl FieldInfo for FieldInfoImpl {}
-
-#[cfg(test)]
-mod field_info_impl_tests {
- use super::*;
- use crate::dtmi::{create_dtmi, Dtmi};
- use crate::model_parser::DTDL_VERSION;
- use crate::primitive_schema_info_impl::PrimitiveSchemaInfoImpl;
- use serde_json;
-
- #[test]
- fn new_field_info_impl_test() -> Result<(), String> {
- let id_result: Option = create_dtmi("dtmi:com:example:Field;1.0");
- assert!(id_result.is_some());
- let id = id_result.unwrap();
-
- let child_of_result: Option = create_dtmi("dtmi:com:example:Cabin;1.0");
- assert!(child_of_result.is_some());
- let child_of = child_of_result.unwrap();
-
- let defined_in_result: Option = create_dtmi("dtmi:com:example;1.0");
- assert!(defined_in_result.is_some());
- let defined_in = defined_in_result.unwrap();
-
- let first_propery_value: Value = serde_json::from_str("{\"first\": \"this\"}").unwrap();
- let second_propery_value: Value = serde_json::from_str("{\"second\": \"that\"}").unwrap();
-
- let schema_info_id: Option = create_dtmi("dtmi:dtdl:class:String;2");
- assert!(schema_info_id.is_some());
-
- let boxed_schema_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- schema_info_id.unwrap(),
- None,
- None,
- EntityKind::String,
- ));
-
- let mut field_info = FieldInfoImpl::new(
- DTDL_VERSION,
- id.clone(),
- Some(child_of.clone()),
- Some(defined_in.clone()),
- Some(String::from("one")),
- Some(boxed_schema_info),
- );
- field_info.add_undefined_property(String::from("first"), first_propery_value.clone());
- field_info.add_undefined_property(String::from("second"), second_propery_value.clone());
-
- assert_eq!(field_info.dtdl_version(), 2);
- assert_eq!(field_info.id(), &id);
- assert!(field_info.child_of().is_some());
- assert_eq!(field_info.child_of().clone().unwrap(), child_of);
- assert!(field_info.defined_in().is_some());
- assert_eq!(field_info.defined_in().clone().unwrap(), defined_in);
- assert_eq!(field_info.entity_kind(), EntityKind::Telemetry);
- assert_eq!(field_info.undefined_properties().len(), 2);
- assert_eq!(
- field_info.undefined_properties().get("first").unwrap().clone(),
- first_propery_value
- );
- assert_eq!(
- field_info.undefined_properties().get("second").unwrap().clone(),
- second_propery_value
- );
-
- match field_info.name() {
- Some(name) => assert_eq!(name, "one"),
- None => return Err(String::from("name has not been set")),
- }
-
- match field_info.schema() {
- Some(schema) => assert_eq!(schema.entity_kind(), EntityKind::String),
- None => return Err(String::from("schema has not been set")),
- }
-
- Ok(())
- }
-}
diff --git a/dtdl-parser/src/interface_info.rs b/dtdl-parser/src/interface_info.rs
deleted file mode 100644
index 7b63776b..00000000
--- a/dtdl-parser/src/interface_info.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::entity_info::EntityInfo;
-
-/// An interface specifies a collection of Commands, Components, Properties, Relationships and Telemetries.
-pub trait InterfaceInfo: EntityInfo {}
diff --git a/dtdl-parser/src/interface_info_impl.rs b/dtdl-parser/src/interface_info_impl.rs
deleted file mode 100644
index ec64adca..00000000
--- a/dtdl-parser/src/interface_info_impl.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use serde_json::Value;
-use std::any::Any;
-use std::collections::HashMap;
-
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-use crate::entity_kind::EntityKind;
-use crate::interface_info::InterfaceInfo;
-
-#[derive(Clone)]
-pub struct InterfaceInfoImpl {
- // EntitytInfo
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- description: Option,
- display_name: Option,
- undefined_properties: HashMap,
-}
-
-impl InterfaceInfoImpl {
- /// Returns a new InterfaceInfoImpl.
- ///
- /// # Arguments
- /// * `dtdl_version` - The DTDL version used to define the interface.
- /// * `id` - The identifier.
- /// * `child_of` - The identifier of the parent element in which this interface is defined.
- /// * `defined_in` - The identifier of the partition in which this interface is defined.
- pub fn new(
- dtdl_version: i32,
- id: Dtmi,
- child_of: Option,
- defined_in: Option,
- ) -> Self {
- Self {
- dtdl_version,
- id,
- child_of,
- defined_in,
- description: None,
- display_name: None,
- undefined_properties: HashMap::::new(),
- }
- }
-
- /// Add an undefined property.
- /// # Arguments
- /// * `key` - The property's name.
- /// * `value` - The property's value.
- pub fn add_undefined_property(&mut self, key: String, value: Value) {
- self.undefined_properties.insert(key, value);
- }
-}
-
-impl EntityInfo for InterfaceInfoImpl {
- /// Returns the DTDL version.
- fn dtdl_version(&self) -> i32 {
- self.dtdl_version
- }
-
- /// Returns the identifier.
- fn id(&self) -> &Dtmi {
- &self.id
- }
-
- /// Returns the kind of entity.
- fn entity_kind(&self) -> EntityKind {
- EntityKind::Interface
- }
-
- /// Returns the parent's identifier.
- fn child_of(&self) -> &Option {
- &self.child_of
- }
-
- /// Returns the enclosing partition's identifier.
- fn defined_in(&self) -> &Option {
- &self.defined_in
- }
-
- // Returns the description for this entity.
- fn description(&self) -> &Option {
- &self.description
- }
-
- // Returns the display name for this entity.
- fn display_name(&self) -> &Option {
- &self.display_name
- }
-
- /// Returns all undefined properties.
- fn undefined_properties(&self) -> &HashMap {
- &self.undefined_properties
- }
-
- /// Returns the instance as an Any.
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
-impl InterfaceInfo for InterfaceInfoImpl {}
-
-#[cfg(test)]
-mod interface_info_impl_tests {
- use super::*;
- use crate::dtmi::{create_dtmi, Dtmi};
- use crate::model_parser::DTDL_VERSION;
- use serde_json;
-
- #[test]
- fn new_interface_info_impl_test() {
- let id_result: Option = create_dtmi("dtmi:com:example:my_interface;1.0");
- assert!(id_result.is_some());
- let id = id_result.unwrap();
-
- let child_of_result: Option = create_dtmi("dtmi:com:example:vehicle;1.0");
- assert!(child_of_result.is_some());
- let child_of = child_of_result.unwrap();
-
- let defined_in_result: Option = create_dtmi("dtmi:com:example;1.0");
- assert!(defined_in_result.is_some());
- let defined_in = defined_in_result.unwrap();
-
- let first_propery_value: Value = serde_json::from_str("{\"first\": \"this\"}").unwrap();
- let second_propery_value: Value = serde_json::from_str("{\"second\": \"that\"}").unwrap();
-
- let mut interface_info = InterfaceInfoImpl::new(
- DTDL_VERSION,
- id.clone(),
- Some(child_of.clone()),
- Some(defined_in.clone()),
- );
- interface_info.add_undefined_property(String::from("first"), first_propery_value.clone());
- interface_info.add_undefined_property(String::from("second"), second_propery_value.clone());
-
- assert_eq!(interface_info.dtdl_version(), 2);
- assert_eq!(interface_info.id(), &id);
- assert!(interface_info.child_of().is_some());
- assert_eq!(interface_info.child_of().clone().unwrap(), child_of);
- assert!(interface_info.defined_in().is_some());
- assert_eq!(interface_info.defined_in().clone().unwrap(), defined_in);
- assert_eq!(interface_info.entity_kind(), EntityKind::Interface);
- assert_eq!(interface_info.undefined_properties().len(), 2);
- assert_eq!(
- interface_info.undefined_properties().get("first").unwrap().clone(),
- first_propery_value
- );
- assert_eq!(
- interface_info.undefined_properties().get("second").unwrap().clone(),
- second_propery_value
- );
- }
-}
diff --git a/dtdl-parser/src/lib.rs b/dtdl-parser/src/lib.rs
deleted file mode 100644
index 61a1ca45..00000000
--- a/dtdl-parser/src/lib.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-#[macro_use]
-extern crate lazy_static;
-
-extern crate json_ld;
-
-pub mod command_info;
-pub mod command_info_impl;
-pub mod command_payload_info;
-pub mod command_payload_info_impl;
-pub mod complex_schema_info;
-pub mod component_info;
-pub mod component_info_impl;
-pub mod content_info;
-pub mod dtmi;
-pub mod entity_info;
-pub mod entity_kind;
-pub mod field_info;
-pub mod field_info_impl;
-pub mod interface_info;
-pub mod interface_info_impl;
-pub mod model_dict;
-pub mod model_parser;
-pub mod named_entity_info;
-pub mod object_info;
-pub mod object_info_impl;
-pub mod primitive_schema_info;
-pub mod primitive_schema_info_impl;
-pub mod primitive_schema_kinds;
-pub mod property_info;
-pub mod property_info_impl;
-pub mod relationship_info;
-pub mod relationship_info_impl;
-pub mod schema_field_info;
-pub mod schema_info;
-pub mod telemetry_info;
-pub mod telemetry_info_impl;
diff --git a/dtdl-parser/src/model_dict.rs b/dtdl-parser/src/model_dict.rs
deleted file mode 100644
index 182bf0f1..00000000
--- a/dtdl-parser/src/model_dict.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use crate::dtmi::Dtmi;
-use crate::entity_info::EntityInfo;
-
-use std::collections::HashMap;
-
-pub type ModelDict = HashMap>;
diff --git a/dtdl-parser/src/model_parser.rs b/dtdl-parser/src/model_parser.rs
deleted file mode 100644
index 6b8216ef..00000000
--- a/dtdl-parser/src/model_parser.rs
+++ /dev/null
@@ -1,1175 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-// SPDX-License-Identifier: MIT
-
-use futures::executor::block_on;
-use json_ld::{context, Document, NoLoader, Node, Object};
-use log::warn;
-use serde_json::{Map, Value};
-use std::collections::HashMap;
-use std::env;
-use std::fs;
-use std::path::Path;
-use std::str::FromStr;
-use strum::IntoEnumIterator;
-
-use crate::command_info_impl::CommandInfoImpl;
-use crate::command_payload_info::CommandPayloadInfo;
-use crate::command_payload_info_impl::CommandPayloadInfoImpl;
-use crate::component_info_impl::ComponentInfoImpl;
-use crate::dtmi::{create_dtmi, Dtmi};
-use crate::entity_kind::EntityKind;
-use crate::field_info::FieldInfo;
-use crate::field_info_impl::FieldInfoImpl;
-use crate::interface_info::InterfaceInfo;
-use crate::interface_info_impl::InterfaceInfoImpl;
-use crate::json_ld::util::AsJson;
-use crate::model_dict::ModelDict;
-use crate::object_info_impl::ObjectInfoImpl;
-use crate::primitive_schema_info_impl::PrimitiveSchemaInfoImpl;
-use crate::primitive_schema_kinds::is_primitive_schema_kind;
-use crate::property_info_impl::PropertyInfoImpl;
-use crate::relationship_info_impl::RelationshipInfoImpl;
-use crate::schema_info::SchemaInfo;
-use crate::telemetry_info_impl::TelemetryInfoImpl;
-
-/// The DTDL Version that the parser supports.
-pub const DTDL_VERSION: i32 = 2;
-
-/// Instances of the ModelParser class parse models written in the DTDL language.
-/// This class can be used to determine: whether one or more DTDL models are valid,
-/// to identify specific modeling errors, and to enable inspection of model contents.
-pub struct ModelParser {}
-
-impl Default for ModelParser {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl ModelParser {
- /// The DTDL-path environment variable name.
- pub const DTDL_PATH: &str = "DTDL_PATH";
-
- /// Returns a new ModelParser instance.
- pub fn new() -> Self {
- Self {}
- }
-
- /// Parse a list of JSON texts and return the resulting model dictionary.
- ///
- /// # Arguments
- /// * `json_texts` - A list of JSON texts.
- pub fn parse(&mut self, json_texts: &Vec) -> Result {
- let mut model_dict: ModelDict = ModelDict::new();
-
- self.add_primitive_schemas_to_model_dict(&mut model_dict)?;
-
- // Add the entries to the model dictionary for the primitive entity kinds.
- for entity_kind in EntityKind::iter() {
- if is_primitive_schema_kind(entity_kind) {
- let schema_info_id: Option = create_dtmi(&entity_kind.to_string());
- if schema_info_id.is_none() {
- return Err(format!(
- "Cannot form a valid schema id for primitive entity kind '{entity_kind}."
- ));
- }
-
- let boxed_entity_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- schema_info_id.clone().unwrap(),
- None,
- None,
- entity_kind,
- ));
- model_dict.insert(schema_info_id.clone().unwrap(), boxed_entity_info);
- }
- }
-
- for json_text in json_texts {
- let mut doc: Value = match serde_json::from_str(json_text) {
- Ok(json) => json,
- Err(error) => {
- return Err(format!("Failed to parse one of the JSON texts due to: {error}"))
- }
- };
-
- self.preprocess(&mut doc)?;
-
- let mut loader = NoLoader::::new();
- let dtdl_doc =
- block_on(doc.expand::, _>(&mut loader)).map_err(|error| {
- format!("Failed to expand one of the JSON texts due to: {error:?}")
- })?;
-
- for item in dtdl_doc.iter() {
- let object: &Object = item;
- if let Object::Node(node) = object {
- self.parse_node(node, &None, &mut model_dict)?;
- }
- }
- }
-
- Ok(model_dict)
- }
-
- /// Add the entries to the model dictionary for the primitive schemas.
- ///
- /// # Arguments
- /// * `model_dict` - The model dictionary.
- fn add_primitive_schemas_to_model_dict(
- &mut self,
- model_dict: &mut ModelDict,
- ) -> Result<(), String> {
- for entity_kind in EntityKind::iter() {
- if is_primitive_schema_kind(entity_kind) {
- let schema_info_id: Option = create_dtmi(&entity_kind.to_string());
- if schema_info_id.is_none() {
- return Err(format!(
- "Cannot form a valid schema id for primitive schema {entity_kind}."
- ));
- }
-
- let boxed_entity_info = Box::new(PrimitiveSchemaInfoImpl::new(
- DTDL_VERSION,
- schema_info_id.clone().unwrap(),
- None,
- None,
- entity_kind,
- ));
- model_dict.insert(schema_info_id.clone().unwrap(), boxed_entity_info);
- }
- }
-
- Ok(())
- }
-
- /// Retrieve a JSON-LD context as a JSON object from the location specified in the filepath.
- ///
- /// # Arguments
- /// * `filepath` - The file path where the context is located.
- fn retrieve_context(&mut self, filepath: &Path) -> Result {
- let contents: String = match fs::read_to_string(filepath) {
- Ok(data) => data,
- Err(error) => {
- return Err(format!(
- "Unable to read the context located at {} due to: {:?}",
- filepath.display(),
- error
- ))
- }
- };
-
- let doc: Value = match serde_json::from_str(&contents) {
- Ok(json) => json,
- Err(error) => {
- return Err(format!(
- "Unable to parse the context located at {} due to: {:?}",
- filepath.display(),
- error
- ))
- }
- };
-
- Ok(doc)
- }
-
- /// Replace a name reference for a context in a JSON object with its respective JSON value.
- ///
- /// # Arguments
- /// * `obj` - The JSON object represented as a map of names to JSON objects.
- /// * `context_name` - The name of the context that we want to replace.
- /// * 'context_value` - The JSON object that we will replace it with.
- #[allow(clippy::needless_range_loop)]
- fn replace_context_inline_in_object(
- &mut self,
- obj: &mut Map,
- context_name: &str,
- context_value: &Value,
- ) -> Result<(), String> {
- let existing_context_value_option = obj.get_mut("@context");
- if let Some(existing_context_value) = existing_context_value_option {
- if let Value::String(s) = existing_context_value {
- if s == context_name {
- obj.remove("@context");
- obj.insert(String::from("@context"), context_value.clone());
- }
- } else if let Value::Array(a) = existing_context_value {
- for i in 0..a.len() {
- if let Value::String(_) = &a[i] {
- if a[i] == context_name {
- a[i] = context_value.clone();
- break;
- }
- }
- }
- } else if let Value::Object(_o) = existing_context_value {
- // ignore - this one does not have an IRI associated with it.
- } else {
- return Err(format!("Unexpected context value '{existing_context_value:?}'"));
- }
- }
- Ok(())
- }
-
- /// Replace a name reference for a context in a JSON-LD document with its respective JSON value.
- ///
- /// # Arguments
- /// * `doc` - The JSON document.
- /// * `context_name` - The name of the context that we want to replace.
- /// * 'context_value` - The JSON object that we will replace it with.
- fn replace_context_inline_in_doc(
- &mut self,
- doc: &mut Value,
- context_name: &str,
- context_value: &Value,
- ) -> Result<(), String> {
- match doc {
- Value::Array(array) => {
- for v in array.iter_mut() {
- self.replace_context_inline_in_doc(v, context_name, context_value)?;
- }
- }
- Value::Object(object) => {
- self.replace_context_inline_in_object(object, context_name, context_value)?;
- }
- _ => warn!("An unexpected json value was encountered"),
- }
- Ok(())
- }
-
- /// Preprocess a JSON-LD document, so that supported dtmi contexts will have their names replaced by their respective JSON.
- ///
- /// # Arguments
- /// * `doc` - The JSON-LD document to preprocess.
- ///
- /// # Examples of supported context formats:
- ///
- /// "@context": "https://json-ld.org/contexts/person.json"
- ///
- /// "@context": [
- /// "https://json-ld.org/contexts/person.json",
- /// "https://json-ld.org/contexts/place.json",
- /// {"title": "http://purl.org/dc/terms/title"}
- /// ]
- fn preprocess(&mut self, doc: &mut Value) -> Result<(), String> {
- let dtdl_2_context_path_string = Self::find_full_path("v2/context/DTDL.v2.context.json")?;
- let dtdl_2_context_path_string_unwrapped = dtdl_2_context_path_string;
- let dtdl_2_context_path = Path::new(&dtdl_2_context_path_string_unwrapped);
- let dtdl_2_context_value = self.retrieve_context(dtdl_2_context_path)?;
- self.replace_context_inline_in_doc(doc, "dtmi:dtdl:context;2", &dtdl_2_context_value)?;
-
- Ok(())
- }
-
- /// Get a property value from a node by name.
- ///
- /// # Arguments
- /// * `node` - The node that contains the property.
- /// * `property_name` - The name of the property.
- fn get_property_value(
- &self,
- node: &Node,
- property_name: &str,
- ) -> Result