Skip to main content

iquery/
types.rs

1// Copyright 2020 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 std::str::FromStr;
6use thiserror::Error;
7
8#[cfg(feature = "fdomain")]
9use component_debug_fdomain as component_debug;
10#[cfg(target_os = "fuchsia")]
11use diagnostics_reader as reader;
12
13use flex_fuchsia_developer_remotecontrol::ConnectCapabilityError;
14
15#[derive(Error, Debug)]
16pub enum Error {
17    #[cfg(target_os = "fuchsia")]
18    #[error("Error while fetching data: {0}")]
19    Fetch(reader::Error),
20
21    #[error("Invalid format: {0}")]
22    InvalidFormat(String),
23
24    #[error("Invalid arguments: {0}")]
25    InvalidArguments(String),
26
27    #[error("Failed formatting the command response: {0}")]
28    InvalidCommandResponse(serde_json::Error),
29
30    #[error("Failed parsing selector {0}: {1}")]
31    ParseSelector(String, anyhow::Error),
32
33    #[error("Failed to list archive accessors on {0} {1}")]
34    ListAccessors(String, anyhow::Error),
35
36    #[error("Error while communicating with {0}: {1}")]
37    CommunicatingWith(String, #[source] anyhow::Error),
38
39    #[error("Failed to connect to {0}: {1}")]
40    ConnectToProtocol(String, #[source] anyhow::Error),
41
42    #[error("IO error. Failed to {0}: {1}")]
43    IOError(String, #[source] anyhow::Error),
44
45    #[error("No running component was found whose URL contains the given string: {0}")]
46    ManifestNotFound(String),
47
48    #[error("No running components were found matching {0}")]
49    SearchParameterNotFound(String),
50
51    #[error("Invalid selector: {0}")]
52    InvalidSelector(String),
53
54    #[error("Invalid accessor: {0}")]
55    InvalidAccessor(String),
56
57    #[error(transparent)]
58    GetManifestError(#[from] component_debug::realm::GetDeclarationError),
59
60    #[error(transparent)]
61    GetAllInstancesError(#[from] component_debug::realm::GetAllInstancesError),
62
63    #[error(transparent)]
64    SocketConversionError(#[from] std::io::Error),
65
66    #[error(transparent)]
67    FidlError(#[from] fidl::Error),
68
69    #[error("Not enough dots in selector")]
70    NotEnoughDots,
71
72    #[error("Must be an exact moniker. Wildcards are not supported.")]
73    MustBeExactMoniker,
74
75    #[error("Must use a property selector to specify the protocol.")]
76    MustUsePropertySelector,
77
78    #[error("Failed to connect to capability {0:?}")]
79    FailedToConnectToCapability(ConnectCapabilityError),
80
81    #[error("Must be exact protocol (protocol cannot contain wildcards)")]
82    MustBeExactProtocol,
83
84    #[error(transparent)]
85    FuzzyMatchRealmQuery(anyhow::Error),
86
87    #[error("Fuzzy matching failed due to too many matches, please re-try with one of these:\n{0}")]
88    FuzzyMatchTooManyMatches(FuzzyMatchErrorWrapper),
89
90    #[error(
91        "hint: positional selectors paired with --data must not include tree/node selector segment: {0}"
92    )]
93    PartialSelectorHint(#[source] selectors::Error),
94
95    #[error(
96        "When using --data, there must be exactly one component query as a positional argument"
97    )]
98    WrongNumberOfSearchQueriesForDataFlag,
99}
100
101#[derive(Debug)]
102pub struct FuzzyMatchErrorWrapper(Vec<String>);
103
104impl std::iter::FromIterator<String> for FuzzyMatchErrorWrapper {
105    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
106        Self(iter.into_iter().collect())
107    }
108}
109
110impl std::fmt::Display for FuzzyMatchErrorWrapper {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
112        for component in &self.0 {
113            writeln!(f, "{component}")?;
114        }
115
116        Ok(())
117    }
118}
119
120impl From<ConnectCapabilityError> for Error {
121    fn from(value: ConnectCapabilityError) -> Self {
122        Self::FailedToConnectToCapability(value)
123    }
124}
125
126impl Error {
127    pub fn invalid_accessor(name: impl Into<String>) -> Error {
128        Error::InvalidAccessor(name.into())
129    }
130
131    pub fn invalid_format(format: impl Into<String>) -> Error {
132        Error::InvalidFormat(format.into())
133    }
134
135    pub fn invalid_arguments(msg: impl Into<String>) -> Error {
136        Error::InvalidArguments(msg.into())
137    }
138
139    pub fn io_error(msg: impl Into<String>, e: anyhow::Error) -> Error {
140        Error::IOError(msg.into(), e)
141    }
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
145pub enum Format {
146    Text,
147    Json,
148}
149
150impl FromStr for Format {
151    type Err = Error;
152
153    fn from_str(s: &str) -> Result<Self, Self::Err> {
154        match s.to_lowercase().as_ref() {
155            "json" => Ok(Format::Json),
156            "text" => Ok(Format::Text),
157            f => Err(Error::invalid_format(f)),
158        }
159    }
160}