iquery/
types.rs

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
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::str::FromStr;
use thiserror::Error;

#[cfg(target_os = "fuchsia")]
use diagnostics_reader as reader;
use fidl_fuchsia_developer_remotecontrol::ConnectCapabilityError;

#[derive(Error, Debug)]
pub enum Error {
    #[cfg(target_os = "fuchsia")]
    #[error("Error while fetching data: {0}")]
    Fetch(reader::Error),

    #[error("Invalid format: {0}")]
    InvalidFormat(String),

    #[error("Invalid arguments: {0}")]
    InvalidArguments(String),

    #[error("Failed formatting the command response: {0}")]
    InvalidCommandResponse(serde_json::Error),

    #[error("Failed parsing selector {0}: {1}")]
    ParseSelector(String, anyhow::Error),

    #[error("Failed to list archive accessors on {0} {1}")]
    ListAccessors(String, anyhow::Error),

    #[error("Error while communicating with {0}: {1}")]
    CommunicatingWith(String, #[source] anyhow::Error),

    #[error("Failed to connect to {0}: {1}")]
    ConnectToProtocol(String, #[source] anyhow::Error),

    #[error("IO error. Failed to {0}: {1}")]
    IOError(String, #[source] anyhow::Error),

    #[error("No running component was found whose URL contains the given string: {0}")]
    ManifestNotFound(String),

    #[error("No running components were found matching {0}")]
    SearchParameterNotFound(String),

    #[error("Invalid selector: {0}")]
    InvalidSelector(String),

    #[error("Invalid accessor: {0}")]
    InvalidAccessor(String),

    #[error(transparent)]
    GetManifestError(#[from] component_debug::realm::GetDeclarationError),

    #[error(transparent)]
    GetAllInstancesError(#[from] component_debug::realm::GetAllInstancesError),

    #[error(transparent)]
    SocketConversionError(#[from] std::io::Error),

    #[error(transparent)]
    FidlError(#[from] fidl::Error),

    #[error("Not enough dots in selector")]
    NotEnoughDots,

    #[error("Must be an exact moniker. Wildcards are not supported.")]
    MustBeExactMoniker,

    #[error("Must use a property selector to specify the protocol.")]
    MustUsePropertySelector,

    #[error("Failed to connect to capability {0:?}")]
    FailedToConnectToCapability(ConnectCapabilityError),

    #[error("Must be exact protocol (protocol cannot contain wildcards)")]
    MustBeExactProtocol,

    #[error(transparent)]
    FuzzyMatchRealmQuery(anyhow::Error),

    #[error(
        "Fuzzy matching failed due to too many matches, please re-try with one of these:\n{0}"
    )]
    FuzzyMatchTooManyMatches(FuzzyMatchErrorWrapper),

    #[error(
        "hint: selectors paired with --component must not include component selector segment: {0}"
    )]
    PartialSelectorHint(#[source] selectors::Error),
}

#[derive(Debug)]
pub struct FuzzyMatchErrorWrapper(Vec<String>);

impl std::iter::FromIterator<String> for FuzzyMatchErrorWrapper {
    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
        Self(iter.into_iter().collect())
    }
}

impl std::fmt::Display for FuzzyMatchErrorWrapper {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        for component in &self.0 {
            writeln!(f, "{component}")?;
        }

        Ok(())
    }
}

impl From<ConnectCapabilityError> for Error {
    fn from(value: ConnectCapabilityError) -> Self {
        Self::FailedToConnectToCapability(value)
    }
}

impl Error {
    pub fn invalid_accessor(name: impl Into<String>) -> Error {
        Error::InvalidAccessor(name.into())
    }

    pub fn invalid_format(format: impl Into<String>) -> Error {
        Error::InvalidFormat(format.into())
    }

    pub fn invalid_arguments(msg: impl Into<String>) -> Error {
        Error::InvalidArguments(msg.into())
    }

    pub fn io_error(msg: impl Into<String>, e: anyhow::Error) -> Error {
        Error::IOError(msg.into(), e)
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Format {
    Text,
    Json,
}

impl FromStr for Format {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_ref() {
            "json" => Ok(Format::Json),
            "text" => Ok(Format::Text),
            f => Err(Error::invalid_format(f)),
        }
    }
}