8585//! All components support optional extensions through [`ExtensionMap`] for future expandability.
8686
8787use crate :: {
88- generate_tagged, AttestKeyTripleRecord , ConditionalEndorsementSeriesTripleRecord ,
88+ core:: { RawValueType , TaggedBytes } ,
89+ generate_tagged,
90+ triples:: { EnvironmentMap , MeasuredElementTypeChoice , MeasurementMap , MeasurementValuesMap } ,
91+ AttestKeyTripleRecord , ConditionalEndorsementSeriesTripleRecord ,
8992 ConditionalEndorsementTripleRecord , CoswidTripleRecord , DomainDependencyTripleRecord ,
9093 DomainMembershipTripleRecord , EndorsedTripleRecord , ExtensionMap , IdentityTripleRecord ,
9194 OneOrMany , ReferenceTripleRecord , Text , Tstr , Uint , Uri , UuidType ,
@@ -104,7 +107,7 @@ generate_tagged!((
104107 "A Concise Module Identifier (CoMID) structured tag"
105108) , ) ;
106109/// A Concise Module Identifier (CoMID) tag structure tagged with CBOR tag 506
107- #[ derive( Debug , Serialize , Deserialize , From , Constructor ) ]
110+ #[ derive( Debug , Serialize , Deserialize , From , Constructor , PartialEq , Eq , PartialOrd , Ord ) ]
108111#[ repr( C ) ]
109112pub struct ConciseMidTag < ' a > {
110113 /// Optional language identifier for the tag content
@@ -126,8 +129,141 @@ pub struct ConciseMidTag<'a> {
126129 pub extension : Option < ExtensionMap < ' a > > ,
127130}
128131
132+ impl < ' a > ConciseMidTag < ' a > {
133+ /// Adds a reference value to the CoMID tag's reference triples.
134+ ///
135+ /// This method serializes the provided value to CBOR bytes and adds it as a raw measurement value
136+ /// within a reference triple. If a reference triple with the same environment already exists,
137+ /// the measurement is added to that triple. Otherwise, a new reference triple is created.
138+ ///
139+ /// # Arguments
140+ ///
141+ /// * `environment` - The environment map that describes the context for this reference value
142+ /// * `mkey` - Optional measurement element type that identifies what is being measured
143+ /// * `value` - The value to serialize and store as the reference value
144+ ///
145+ /// # Returns
146+ ///
147+ /// Returns `Ok(())` if successful, or an `std::io::Error` if serialization fails.
148+ ///
149+ /// # Example
150+ ///
151+ /// ``` ignore
152+ /// use corim_rs::{
153+ /// comid::{ConciseMidTag, TagIdentityMap, ComidEntityMap, TriplesMap, TagIdTypeChoice},
154+ /// core::{OneOrMore, Text, Tstr},
155+ /// triples::{EnvironmentMap, MeasuredElementTypeChoice},
156+ /// };
157+ ///
158+ /// let mut comid = ConciseMidTag {
159+ /// language: None,
160+ /// tag_identity: TagIdentityMap {
161+ /// tag_id: TagIdTypeChoice::Tstr(Tstr::from("example-id")),
162+ /// tag_version: Some(1),
163+ /// },
164+ /// entities: OneOrMore::One(ComidEntityMap {
165+ /// entity_name: Text::from("Example Corp"),
166+ /// reg_id: None,
167+ /// role: OneOrMore::One(corim_rs::comid::ComidRoleTypeChoice::TagCreator),
168+ /// extension: None,
169+ /// }),
170+ /// linked_tags: None,
171+ /// triples: TriplesMap::default(),
172+ /// extension: None,
173+ /// };
174+ ///
175+ /// // Add a reference value
176+ /// let env = EnvironmentMap::default();
177+ /// let reference_data = "example reference value";
178+ /// comid.add_reference_value(env, None, &reference_data).expect("Failed to add reference value");
179+ /// ```
180+ ///
181+ /// # How It Works
182+ ///
183+ /// 1. The value is serialized to CBOR bytes using the `ciborium` library
184+ /// 2. The bytes are wrapped in a `TaggedBytes` structure
185+ /// 3. A `MeasurementMap` is created with the provided measurement key and the raw value
186+ /// 4. The method then updates the CoMID's reference triples based on existing data:
187+ /// - If no reference triples exist, a new one is created
188+ /// - If a reference triple with the matching environment exists, the measurement is added to it
189+ /// - If reference triples exist but none match the environment, a new triple is added
190+ pub fn add_reference_value < T > (
191+ & mut self ,
192+ environment : EnvironmentMap < ' a > ,
193+ mkey : Option < MeasuredElementTypeChoice < ' a > > ,
194+ value : & T ,
195+ ) -> Result < ( ) , std:: io:: Error >
196+ where
197+ T : ?Sized + Serialize ,
198+ {
199+ let mut raw_bytes = vec ! [ ] ;
200+ ciborium:: into_writer ( value, & mut raw_bytes)
201+ . map_err ( |e| std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , e. to_string ( ) ) ) ?;
202+ let raw_value = TaggedBytes :: new ( raw_bytes) ;
203+
204+ let measurement = MeasurementMap {
205+ mkey,
206+ mval : MeasurementValuesMap {
207+ raw : Some ( RawValueType {
208+ raw_value : raw_value. into ( ) ,
209+ raw_value_mask : None ,
210+ } ) ,
211+ ..Default :: default ( )
212+ } ,
213+ authorized_by : None ,
214+ } ;
215+
216+ match & mut self . triples . reference_triples {
217+ None => {
218+ let new_record = ReferenceTripleRecord {
219+ ref_env : environment,
220+ ref_claims : measurement. into ( ) ,
221+ } ;
222+ self . triples . reference_triples = Some ( OneOrMany :: One ( new_record) ) ;
223+ }
224+ Some ( OneOrMany :: One ( record) ) => {
225+ if record. ref_env == environment {
226+ match & mut record. ref_claims {
227+ OneOrMany :: One ( original_claim) => {
228+ record. ref_claims =
229+ OneOrMany :: Many ( vec ! [ std:: mem:: take( original_claim) , measurement] )
230+ }
231+ OneOrMany :: Many ( claims) => claims. push ( measurement) ,
232+ }
233+ } else {
234+ let new_record: ReferenceTripleRecord < ' a > = ReferenceTripleRecord {
235+ ref_env : environment,
236+ ref_claims : measurement. into ( ) ,
237+ } ;
238+
239+ let many = vec ! [ std:: mem:: take( record) , new_record] ;
240+ self . triples . reference_triples = Some ( OneOrMany :: Many ( many) ) ;
241+ }
242+ }
243+ Some ( OneOrMany :: Many ( vec) ) => {
244+ if let Some ( record) = vec. iter_mut ( ) . find ( |r| r. ref_env == environment) {
245+ match & mut record. ref_claims {
246+ OneOrMany :: One ( claim) => {
247+ record. ref_claims =
248+ OneOrMany :: Many ( vec ! [ std:: mem:: take( claim) , measurement] )
249+ }
250+ OneOrMany :: Many ( claims) => claims. push ( measurement) ,
251+ }
252+ } else {
253+ let new_record = ReferenceTripleRecord {
254+ ref_env : environment,
255+ ref_claims : measurement. into ( ) ,
256+ } ;
257+ vec. push ( new_record) ;
258+ }
259+ }
260+ }
261+ Ok ( ( ) )
262+ }
263+ }
264+
129265/// Identification information for a tag
130- #[ derive( Debug , Serialize , Deserialize , From , Constructor ) ]
266+ #[ derive( Debug , Serialize , Deserialize , From , Constructor , PartialEq , Eq , PartialOrd , Ord ) ]
131267#[ repr( C ) ]
132268pub struct TagIdentityMap < ' a > {
133269 /// Unique identifier for the tag
@@ -140,7 +276,7 @@ pub struct TagIdentityMap<'a> {
140276}
141277
142278/// Represents either a string or UUID tag identifier
143- #[ derive( Debug , Serialize , Deserialize , From , TryFrom ) ]
279+ #[ derive( Debug , Serialize , Deserialize , From , TryFrom , PartialEq , Eq , PartialOrd , Ord ) ]
144280#[ repr( C ) ]
145281pub enum TagIdTypeChoice < ' a > {
146282 /// Text string identifier
@@ -156,7 +292,7 @@ impl<'a> From<&'a str> for TagIdTypeChoice<'a> {
156292}
157293
158294/// Information about an entity associated with the tag
159- #[ derive( Debug , Serialize , Deserialize , From , Constructor ) ]
295+ #[ derive( Debug , Serialize , Deserialize , From , Constructor , PartialEq , Eq , PartialOrd , Ord ) ]
160296#[ repr( C ) ]
161297pub struct ComidEntityMap < ' a > {
162298 /// Name of the entity
@@ -175,7 +311,7 @@ pub struct ComidEntityMap<'a> {
175311}
176312
177313/// Role types that can be assigned to entities
178- #[ derive( Debug , Serialize , Deserialize , From , TryFrom ) ]
314+ #[ derive( Debug , Serialize , Deserialize , From , TryFrom , PartialEq , Eq , PartialOrd , Ord ) ]
179315#[ repr( C ) ]
180316pub enum ComidRoleTypeChoice {
181317 /// Entity that created the tag (value: 0)
@@ -187,7 +323,7 @@ pub enum ComidRoleTypeChoice {
187323}
188324
189325/// Reference to another tag and its relationship to this one
190- #[ derive( Debug , Serialize , Deserialize , From , Constructor ) ]
326+ #[ derive( Debug , Serialize , Deserialize , From , Constructor , PartialEq , Eq , PartialOrd , Ord ) ]
191327#[ repr( C ) ]
192328pub struct LinkedTagMap < ' a > {
193329 /// Identifier of the linked tag
@@ -199,7 +335,7 @@ pub struct LinkedTagMap<'a> {
199335}
200336
201337/// Types of relationships between tags
202- #[ derive( Debug , Serialize , Deserialize , From , TryFrom ) ]
338+ #[ derive( Debug , Serialize , Deserialize , From , TryFrom , PartialEq , Eq , PartialOrd , Ord ) ]
203339#[ repr( C ) ]
204340pub enum TagRelTypeChoice {
205341 /// This tag supplements the linked tag by providing additional information
@@ -211,7 +347,7 @@ pub enum TagRelTypeChoice {
211347}
212348
213349/// Collection of different types of triples describing the module characteristics
214- #[ derive( Default , Debug , Serialize , Deserialize , From ) ]
350+ #[ derive( Default , Debug , Serialize , Deserialize , From , PartialEq , Eq , PartialOrd , Ord ) ]
215351#[ repr( C ) ]
216352pub struct TriplesMap < ' a > {
217353 /// Optional reference triples that link to external references
0 commit comments