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