use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use super::{Binding, Module, PackageInput};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ExecutionLane {
id: String,
}
impl ExecutionLane {
pub fn new(id: impl Into<String>) -> Self {
Self { id: id.into() }
}
pub fn id(&self) -> &str {
&self.id
}
}
fn default_execution_lanes() -> Vec<ExecutionLane> {
vec![ExecutionLane::new("main")]
}
pub const PROJECT_SCHEMA_VERSION: u32 = 1;
fn default_project_schema() -> u32 {
PROJECT_SCHEMA_VERSION
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct WebProfile {
shell: String,
browser_adapter: String,
#[serde(default)]
ui_contributions: Vec<String>,
#[serde(default)]
additional_modules: Vec<String>,
}
impl WebProfile {
pub fn new(shell: impl Into<String>, browser_adapter: impl Into<String>) -> Self {
Self {
shell: shell.into(),
browser_adapter: browser_adapter.into(),
ui_contributions: Vec::new(),
additional_modules: Vec::new(),
}
}
#[must_use]
pub fn with_ui_contribution(mut self, instance: impl Into<String>) -> Self {
self.ui_contributions.push(instance.into());
self
}
#[must_use]
pub fn with_module(mut self, instance: impl Into<String>) -> Self {
self.additional_modules.push(instance.into());
self
}
pub fn shell(&self) -> &str {
&self.shell
}
pub fn browser_adapter(&self) -> &str {
&self.browser_adapter
}
pub fn ui_contributions(&self) -> &[String] {
&self.ui_contributions
}
pub fn selected_modules(&self) -> impl Iterator<Item = &str> {
std::iter::once(self.shell())
.chain(std::iter::once(self.browser_adapter()))
.chain(self.ui_contributions.iter().map(String::as_str))
.chain(self.additional_modules.iter().map(String::as_str))
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ContractInput {
capability_id: String,
descriptor_version: String,
descriptor: String,
rust: String,
typescript: String,
}
impl ContractInput {
pub fn new(
capability_id: impl Into<String>,
descriptor_version: impl Into<String>,
descriptor: impl Into<String>,
rust: impl Into<String>,
typescript: impl Into<String>,
) -> Self {
Self {
capability_id: capability_id.into(),
descriptor_version: descriptor_version.into(),
descriptor: descriptor.into(),
rust: rust.into(),
typescript: typescript.into(),
}
}
pub fn capability_id(&self) -> &str {
&self.capability_id
}
pub fn descriptor_version(&self) -> &str {
&self.descriptor_version
}
pub fn descriptor(&self) -> &str {
&self.descriptor
}
pub fn rust(&self) -> &str {
&self.rust
}
pub fn typescript(&self) -> &str {
&self.typescript
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct CompositionFile {
#[serde(default)]
modules: Vec<Module>,
#[serde(default)]
bindings: Vec<Binding>,
#[serde(default = "default_execution_lanes")]
execution_lanes: Vec<ExecutionLane>,
}
impl Default for CompositionFile {
fn default() -> Self {
Self {
modules: Vec::new(),
bindings: Vec::new(),
execution_lanes: default_execution_lanes(),
}
}
}
impl CompositionFile {
pub fn add_module(&mut self, module: Module) {
self.modules.push(module);
}
pub fn modules(&self) -> &[Module] {
&self.modules
}
pub fn modules_mut(&mut self) -> &mut Vec<Module> {
&mut self.modules
}
pub fn add_binding(&mut self, binding: Binding) {
self.bindings.push(binding);
}
pub fn bindings(&self) -> &[Binding] {
&self.bindings
}
pub fn bindings_mut(&mut self) -> &mut Vec<Binding> {
&mut self.bindings
}
pub fn add_execution_lane(&mut self, lane: ExecutionLane) {
if self.execution_lanes.len() == 1 && self.execution_lanes[0].id() == "main" {
self.execution_lanes.clear();
}
self.execution_lanes.push(lane);
}
pub fn execution_lanes(&self) -> &[ExecutionLane] {
&self.execution_lanes
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ProjectFile {
#[serde(default = "default_project_schema")]
schema_version: u32,
#[serde(default)]
composition: CompositionFile,
#[serde(default)]
packages: BTreeMap<String, PackageInput>,
#[serde(default)]
contracts: Vec<ContractInput>,
#[serde(default)]
profiles: BTreeMap<String, WebProfile>,
}
impl Default for ProjectFile {
fn default() -> Self {
Self {
schema_version: PROJECT_SCHEMA_VERSION,
composition: CompositionFile::default(),
packages: BTreeMap::new(),
contracts: Vec::new(),
profiles: BTreeMap::new(),
}
}
}
impl ProjectFile {
pub const fn schema_version(&self) -> u32 {
self.schema_version
}
pub fn composition(&self) -> &CompositionFile {
&self.composition
}
pub fn composition_mut(&mut self) -> &mut CompositionFile {
&mut self.composition
}
pub fn packages(&self) -> &BTreeMap<String, PackageInput> {
&self.packages
}
pub fn packages_mut(&mut self) -> &mut BTreeMap<String, PackageInput> {
&mut self.packages
}
pub fn contracts(&self) -> &[ContractInput] {
&self.contracts
}
pub fn contracts_mut(&mut self) -> &mut Vec<ContractInput> {
&mut self.contracts
}
pub fn profile(&self, name: &str) -> Option<&WebProfile> {
self.profiles.get(name)
}
pub fn profiles_mut(&mut self) -> &mut BTreeMap<String, WebProfile> {
&mut self.profiles
}
}