1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use serde::{Deserialize, Serialize};

use crate::{contents_equal, Field, OperationSignature, TypeDefinition};

/// Signature for Collections.
#[derive(Debug, Clone, Default, Serialize, Deserialize, Eq, derive_builder::Builder)]
#[builder(default)]
#[must_use]
#[non_exhaustive]
pub struct ComponentSignature {
  /// Name of the collection.
  pub name: Option<String>,

  /// The format of the component signature.
  pub format: ComponentVersion,

  /// Component implementation version.
  #[serde(default)]
  pub metadata: ComponentMetadata,

  /// A map of type signatures referenced elsewhere.
  #[serde(default, skip_serializing_if = "Vec::is_empty")]
  pub wellknown: Vec<WellKnownSchema>,

  /// A map of type signatures referenced elsewhere.
  #[serde(default, skip_serializing_if = "Vec::is_empty")]
  pub types: Vec<TypeDefinition>,

  /// A list of [OperationSignature]s in this component.
  #[serde(default, skip_serializing_if = "Vec::is_empty")]
  pub operations: Vec<OperationSignature>,

  /// The component's configuration for this implementation.
  #[serde(default, skip_serializing_if = "Vec::is_empty")]
  pub config: Vec<Field>,
}

impl PartialEq for ComponentSignature {
  fn eq(&self, other: &Self) -> bool {
    let types_equal = contents_equal(&self.types, &other.types);
    let operations_equal = contents_equal(&self.operations, &other.operations);
    let config_equal = contents_equal(&self.config, &other.config);
    let wellknown_equal = contents_equal(&self.wellknown, &other.wellknown);

    self.format == other.format && types_equal && operations_equal && config_equal && wellknown_equal
  }
}

impl ComponentSignature {
  /// Create a new [ComponentSignature] with the passed name.
  pub fn new<T: Into<String>>(
    name: T,
    version: Option<String>,
    operations: Vec<OperationSignature>,
    types: Vec<TypeDefinition>,
    config: Vec<Field>,
  ) -> Self {
    Self {
      name: Some(name.into()),
      metadata: ComponentMetadata::new(version),
      operations,
      types,
      config,
      ..Default::default()
    }
  }

  /// Create a new [ComponentSignature] with the passed name.
  pub fn new_named<T: Into<String>>(name: T) -> Self {
    Self {
      name: Some(name.into()),
      ..Default::default()
    }
  }

  #[must_use]
  /// Get the [OperationSignature] for the requested component.
  pub fn get_operation(&self, operation_name: &str) -> Option<&OperationSignature> {
    self.operations.iter().find(|op| op.name == operation_name)
  }

  /// Add a [OperationSignature] to the collection.
  pub fn add_operation(mut self, signature: OperationSignature) -> Self {
    self.operations.push(signature);
    self
  }

  /// Set the version of the [ComponentSignature].
  pub fn set_version<T: Into<String>>(mut self, version: T) -> Self {
    self.metadata.version = Some(version.into());
    self
  }

  /// Set the format of the [ComponentSignature].
  pub const fn format(mut self, format: ComponentVersion) -> Self {
    self.format = format;
    self
  }

  /// Set the features of the [ComponentSignature].
  #[allow(clippy::missing_const_for_fn)]
  pub fn metadata(self, features: ComponentMetadata) -> Self {
    Self {
      metadata: features,
      ..self
    }
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, serde_repr::Deserialize_repr, serde_repr::Serialize_repr)]
#[must_use]
#[non_exhaustive]
#[repr(u32)]
/// The umbrella version of the component.
pub enum ComponentVersion {
  /// Version 0 Wick components.
  V0 = 0,
  /// Version 1 Wick components.
  V1 = 1,
}

impl Default for ComponentVersion {
  fn default() -> Self {
    Self::V1
  }
}

impl From<ComponentVersion> for u32 {
  fn from(v: ComponentVersion) -> Self {
    match v {
      ComponentVersion::V0 => 0,
      ComponentVersion::V1 => 1,
    }
  }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[must_use]
#[non_exhaustive]
/// The Wick features this collection supports.
pub struct ComponentMetadata {
  /// Version of the component.
  #[serde(skip_serializing_if = "Option::is_none")]
  pub version: Option<String>,
}

impl ComponentMetadata {
  pub const fn new(version: Option<String>) -> Self {
    Self { version }
  }
}

/// An entry from a well-known schema
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct WellKnownSchema {
  /// The capability the schema provides.
  pub capabilities: Vec<String>,
  /// The location where you can find and validate the schema.
  pub url: String,
  /// The schema itself.
  pub schema: ComponentSignature,
}