archivist_lib/
identity.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use diagnostics_message::MonikerWithUrl;
6use flyweights::FlyStr;
7use moniker::{ExtendedMoniker, Moniker};
8use std::hash::{Hash, Hasher};
9
10#[derive(Debug)]
11pub struct ComponentIdentity {
12    /// Moniker of the component that this artifacts container is representing.
13    pub moniker: ExtendedMoniker,
14
15    /// The url with which the associated component was launched.
16    pub url: FlyStr,
17}
18
19// Just use the moniker when hashing and checking equality. That's the unique ID we need. The URL
20// is just used for metadata purposes. Typically both can be used and we can
21// derive(ComponentIdentity), but as long as we have the workaround for netstack2 diagnostics we
22// should just use the moniker as we don't know the runtime URL for this component.
23// TODO(https://fxbug.dev/324494668): consider just derive(Hash) when Netstack2 is gone.
24impl Hash for ComponentIdentity {
25    fn hash<H: Hasher>(&self, state: &mut H) {
26        self.moniker.hash(state);
27    }
28}
29
30impl PartialEq for ComponentIdentity {
31    fn eq(&self, other: &Self) -> bool {
32        self.moniker == other.moniker
33    }
34}
35
36impl PartialEq<Moniker> for ComponentIdentity {
37    fn eq(&self, other: &Moniker) -> bool {
38        matches!(&self.moniker, ExtendedMoniker::ComponentInstance(moniker) if moniker == other)
39    }
40}
41
42impl Eq for ComponentIdentity {}
43
44impl ComponentIdentity {
45    pub fn new(moniker: ExtendedMoniker, url: impl Into<FlyStr>) -> Self {
46        ComponentIdentity { moniker, url: url.into() }
47    }
48
49    /// Returns generic metadata, suitable for providing a uniform ID to unattributed data.
50    pub fn unknown() -> Self {
51        Self::new(
52            ExtendedMoniker::parse_str("/UNKNOWN").expect("Unknown is valid"),
53            "fuchsia-pkg://UNKNOWN",
54        )
55    }
56}
57
58#[cfg(test)]
59impl From<Vec<&str>> for ComponentIdentity {
60    fn from(moniker_segments: Vec<&str>) -> Self {
61        let moniker = moniker::Moniker::try_from(moniker_segments.as_slice()).unwrap();
62        Self { moniker: ExtendedMoniker::from(moniker), url: "".into() }
63    }
64}
65
66impl From<ComponentIdentity> for MonikerWithUrl {
67    fn from(identity: ComponentIdentity) -> Self {
68        Self { moniker: identity.moniker, url: identity.url }
69    }
70}
71
72impl From<&ComponentIdentity> for MonikerWithUrl {
73    fn from(identity: &ComponentIdentity) -> Self {
74        Self { moniker: identity.moniker.clone(), url: identity.url.clone() }
75    }
76}
77
78impl std::fmt::Display for ComponentIdentity {
79    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        self.moniker.fmt(f)
81    }
82}