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
use crate::storage::load::Error as LoadError;
use crate::types::{ActorId, ScalarValue};
use crate::value::DataType;
use crate::{ChangeHash, Cursor, LoadChangeError, ObjType, PatchAction};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AutomergeError {
    #[error(transparent)]
    ChangeGraph(#[from] crate::change_graph::MissingDep),
    #[error("failed to load compressed data: {0}")]
    Deflate(#[source] std::io::Error),
    #[error("duplicate seq {0} found for actor {1}")]
    DuplicateSeqNumber(u64, ActorId),
    #[error("key must not be an empty string")]
    EmptyStringKey,
    #[error("general failure")]
    Fail,
    #[error("invalid actor ID `{0}`")]
    InvalidActorId(String),
    #[error(transparent)]
    InvalidChangeHashBytes(#[from] InvalidChangeHashSlice),
    #[error("invalid UTF-8 character at {0}")]
    InvalidCharacter(usize),
    #[error("invalid hash {0}")]
    InvalidHash(ChangeHash),
    #[error("index {0} is out of bounds")]
    InvalidIndex(usize),
    #[error("invalid obj id `{0}`")]
    InvalidObjId(String),
    #[error("invalid obj id format `{0}`")]
    InvalidObjIdFormat(String),
    #[error("invalid op for object of type `{0}`")]
    InvalidOp(ObjType),
    #[error("seq {0} is out of bounds")]
    InvalidSeq(u64),
    #[error("cursor {0} is invalid")]
    InvalidCursor(Cursor),
    #[error("cursor format is invalid")]
    InvalidCursorFormat,
    #[error("invalid type of value, expected `{expected}` but received `{unexpected}`")]
    InvalidValueType {
        expected: String,
        unexpected: String,
    },
    #[error(transparent)]
    Load(#[from] LoadError),
    #[error(transparent)]
    LoadChangeError(#[from] LoadChangeError),
    #[error("increment operations must be against a counter value")]
    MissingCounter,
    #[error("hash {0} does not correspond to a change in this document")]
    MissingHash(ChangeHash),
    #[error("change's deps should already be in the document")]
    MissingDeps,
    #[error("compressed chunk was not a change")]
    NonChangeCompressed,
    #[error("id was not an object id")]
    NotAnObject,
    #[error(transparent)]
    HydrateError(#[from] HydrateError),
}

impl PartialEq for AutomergeError {
    fn eq(&self, other: &Self) -> bool {
        std::mem::discriminant(self) == std::mem::discriminant(other)
    }
}

#[cfg(feature = "wasm")]
impl From<AutomergeError> for wasm_bindgen::JsValue {
    fn from(err: AutomergeError) -> Self {
        js_sys::Error::new(&std::format!("{}", err)).into()
    }
}

#[derive(Error, Debug)]
#[error("Invalid actor ID: {0}")]
pub struct InvalidActorId(pub String);

#[derive(Error, Debug, PartialEq)]
#[error("Invalid scalar value, expected {expected} but received {unexpected}")]
pub(crate) struct InvalidScalarValue {
    pub(crate) raw_value: ScalarValue,
    pub(crate) datatype: DataType,
    pub(crate) unexpected: String,
    pub(crate) expected: String,
}

#[derive(Error, Debug, Eq, PartialEq)]
#[error("Invalid change hash slice: {0:?}")]
pub struct InvalidChangeHashSlice(pub Vec<u8>);

#[derive(Error, Debug, Eq, PartialEq)]
#[error("Invalid object ID: {0}")]
pub struct InvalidObjectId(pub String);

#[derive(Error, Debug)]
#[error("Invalid element ID: {0}")]
pub struct InvalidElementId(pub String);

#[derive(Error, Debug)]
#[error("Invalid OpID: {0}")]
pub struct InvalidOpId(pub String);

#[derive(Error, Debug)]
pub enum InvalidOpType {
    #[error("unrecognized action index {0}")]
    UnknownAction(u64),
    #[error("non numeric argument for inc op")]
    NonNumericInc,
}

#[derive(Error, Debug)]
pub enum HydrateError {
    //#[error(transparent)]
    //ChangeGraph(#[from] crate::change_graph::MissingDep),
    #[error("general failure")]
    Fail,
    #[error("invalid index {0} for sequence")]
    InvalidIndex(usize),
    #[error("invalid key {0} for map")]
    InvalidKey(String),
    #[error("increment of a non-counter")]
    BadIncrement,
    #[error("invalid op applied to map")]
    InvalidMapOp,
    #[error("invalid op appied to list")]
    InvalidListOp,
    #[error("invalid op applied to map: {0}")]
    InvalidTextOp(PatchAction),
    #[error("invalid prop in patch: {0}")]
    ApplyInvalidProp(PatchAction),
}