summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/bookmark_sync/src/error.rs
blob: 5ac7c5b62ce918deaef946394c17fda3485d3fdb (plain)
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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::{error, fmt, result, string::FromUtf16Error};

use nserror::{
    nsresult, NS_ERROR_ABORT, NS_ERROR_FAILURE, NS_ERROR_INVALID_ARG, NS_ERROR_STORAGE_BUSY,
    NS_ERROR_UNEXPECTED,
};

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Dogear(dogear::Error),
    Storage(storage::Error),
    InvalidLocalRoots,
    InvalidRemoteRoots,
    Nsresult(nsresult),
    UnknownItemType(i64),
    UnknownItemKind(i64),
    MalformedString(Box<dyn error::Error + Send + Sync + 'static>),
    MergeConflict,
    StorageBusy,
    UnknownItemValidity(i64),
    DidNotRun,
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Dogear(err) => Some(err),
            Error::Storage(err) => Some(err),
            _ => None,
        }
    }
}

impl From<dogear::Error> for Error {
    fn from(err: dogear::Error) -> Error {
        Error::Dogear(err)
    }
}

impl From<storage::Error> for Error {
    fn from(err: storage::Error) -> Error {
        Error::Storage(err)
    }
}

impl From<nsresult> for Error {
    fn from(result: nsresult) -> Error {
        Error::Nsresult(result)
    }
}

impl From<FromUtf16Error> for Error {
    fn from(error: FromUtf16Error) -> Error {
        Error::MalformedString(error.into())
    }
}

impl From<Error> for nsresult {
    fn from(error: Error) -> nsresult {
        match error {
            Error::Dogear(err) => match err.kind() {
                dogear::ErrorKind::Abort => NS_ERROR_ABORT,
                _ => NS_ERROR_FAILURE,
            },
            Error::InvalidLocalRoots | Error::InvalidRemoteRoots | Error::DidNotRun => {
                NS_ERROR_UNEXPECTED
            }
            Error::Storage(err) => err.into(),
            Error::Nsresult(result) => result.clone(),
            Error::UnknownItemType(_)
            | Error::UnknownItemKind(_)
            | Error::MalformedString(_)
            | Error::UnknownItemValidity(_) => NS_ERROR_INVALID_ARG,
            Error::MergeConflict | Error::StorageBusy => NS_ERROR_STORAGE_BUSY,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Dogear(err) => err.fmt(f),
            Error::Storage(err) => err.fmt(f),
            Error::InvalidLocalRoots => f.write_str("The Places roots are invalid"),
            Error::InvalidRemoteRoots => {
                f.write_str("The roots in the mirror database are invalid")
            }
            Error::Nsresult(result) => write!(f, "Operation failed with {}", result.error_name()),
            Error::UnknownItemType(typ) => write!(f, "Unknown item type {} in Places", typ),
            Error::UnknownItemKind(kind) => write!(f, "Unknown item kind {} in mirror", kind),
            Error::MalformedString(err) => err.fmt(f),
            Error::MergeConflict => f.write_str("Local tree changed during merge"),
            Error::StorageBusy => f.write_str("The database is busy"),
            Error::UnknownItemValidity(validity) => {
                write!(f, "Unknown item validity {} in database", validity)
            }
            Error::DidNotRun => write!(f, "Failed to run merge on storage thread"),
        }
    }
}