1
use std::fmt::{Display, Write};
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
use crate::document::{BorrowedDocument, CollectionDocument, DocumentId, OwnedDocument, Revision};
6
use crate::key::Key;
7
use crate::schema::view::map::Mappings;
8
use crate::schema::{Map, SerializedCollection};
9

            
10
/// The header of a `Document`.
11
151736321
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
12
pub struct Header {
13
    /// The id of the Document. Unique across the collection the document is
14
    /// contained within.
15
    pub id: DocumentId,
16

            
17
    /// The revision of the stored document.
18
    pub revision: Revision,
19
}
20

            
21
/// A type that can return a [`Header`].
22
pub trait HasHeader {
23
    /// Returns the header for this instance.
24
    fn header(&self) -> Result<Header, crate::Error>;
25
}
26

            
27
impl HasHeader for Header {
28
20680
    fn header(&self) -> Result<Header, crate::Error> {
29
20680
        Ok(self.clone())
30
20680
    }
31
}
32

            
33
/// View mapping emit functions. Used when implementing a view's `map()`
34
/// function.
35
pub trait Emit {
36
    /// Creates a `Map` result with an empty key and value.
37
43
    fn emit(&self) -> Result<Mappings<(), ()>, crate::Error> {
38
43
        self.emit_key_and_value((), ())
39
43
    }
40

            
41
    /// Creates a `Map` result with an empty key and value if `condition` is
42
    /// true.
43
    fn emit_if(&self, condition: bool) -> Result<Mappings<(), ()>, crate::Error> {
44
        if condition {
45
            self.emit()
46
        } else {
47
            Ok(Mappings::default())
48
        }
49
    }
50

            
51
    /// Creates a `Map` result with a `key` and an empty value.
52
11961
    fn emit_key<K>(&self, key: K) -> Result<Mappings<K, ()>, crate::Error> {
53
11961
        self.emit_key_and_value(key, ())
54
11961
    }
55

            
56
    /// Creates a `Map` result with `value` and an empty key.
57
1
    fn emit_value<Value>(&self, value: Value) -> Result<Mappings<(), Value>, crate::Error> {
58
1
        self.emit_key_and_value((), value)
59
1
    }
60

            
61
    /// Creates a `Map` result with a `key` and `value`.
62
    fn emit_key_and_value<K, Value>(
63
        &self,
64
        key: K,
65
        value: Value,
66
    ) -> Result<Mappings<K, Value>, crate::Error>;
67
}
68

            
69
impl Emit for Header {
70
505008
    fn emit_key_and_value<K, Value>(
71
505008
        &self,
72
505008
        key: K,
73
505008
        value: Value,
74
505008
    ) -> Result<Mappings<K, Value>, crate::Error> {
75
505008
        Ok(Mappings::Simple(Some(Map::new(self.clone(), key, value))))
76
505008
    }
77
}
78

            
79
impl Display for Header {
80
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81
1
        self.id.fmt(f)?;
82
1
        f.write_char('@')?;
83
1
        self.revision.fmt(f)
84
1
    }
85
}
86

            
87
/// A header for a [`CollectionDocument`].
88
129836
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
89
pub struct CollectionHeader<PrimaryKey> {
90
    /// The unique id of the document.
91
    pub id: PrimaryKey,
92
    /// The revision of the document.
93
    pub revision: Revision,
94
}
95

            
96
impl<PrimaryKey> Emit for CollectionHeader<PrimaryKey>
97
where
98
    PrimaryKey: for<'k> Key<'k>,
99
{
100
62490
    fn emit_key_and_value<K, Value>(
101
62490
        &self,
102
62490
        key: K,
103
62490
        value: Value,
104
62490
    ) -> Result<Mappings<K, Value>, crate::Error> {
105
62490
        let header = Header::try_from(self.clone())?;
106
62490
        Ok(Mappings::Simple(Some(Map::new(header, key, value))))
107
62490
    }
108
}
109

            
110
impl<PrimaryKey> HasHeader for CollectionHeader<PrimaryKey>
111
where
112
    PrimaryKey: for<'k> Key<'k>,
113
{
114
19522
    fn header(&self) -> Result<Header, crate::Error> {
115
19522
        Header::try_from(self.clone())
116
19522
    }
117
}
118

            
119
impl HasHeader for OwnedDocument {
120
20680
    fn header(&self) -> Result<Header, crate::Error> {
121
20680
        self.header.header()
122
20680
    }
123
}
124

            
125
impl<'a> HasHeader for BorrowedDocument<'a> {
126
    fn header(&self) -> Result<Header, crate::Error> {
127
        self.header.header()
128
    }
129
}
130

            
131
impl<C> HasHeader for CollectionDocument<C>
132
where
133
    C: SerializedCollection,
134
{
135
518
    fn header(&self) -> Result<Header, crate::Error> {
136
518
        self.header.header()
137
518
    }
138
}
139

            
140
impl<PrimaryKey> TryFrom<Header> for CollectionHeader<PrimaryKey>
141
where
142
    PrimaryKey: for<'k> Key<'k>,
143
{
144
    type Error = crate::Error;
145

            
146
758825
    fn try_from(value: Header) -> Result<Self, Self::Error> {
147
758825
        Ok(Self {
148
758825
            id: value.id.deserialize::<PrimaryKey>()?,
149
758825
            revision: value.revision,
150
        })
151
758825
    }
152
}
153

            
154
impl<'a, PrimaryKey> TryFrom<&'a Header> for CollectionHeader<PrimaryKey>
155
where
156
    PrimaryKey: for<'k> Key<'k>,
157
{
158
    type Error = crate::Error;
159

            
160
16
    fn try_from(value: &'a Header) -> Result<Self, Self::Error> {
161
16
        Ok(Self {
162
16
            id: value.id.deserialize::<PrimaryKey>()?,
163
16
            revision: value.revision,
164
        })
165
16
    }
166
}
167

            
168
impl<PrimaryKey> TryFrom<CollectionHeader<PrimaryKey>> for Header
169
where
170
    PrimaryKey: for<'k> Key<'k>,
171
{
172
    type Error = crate::Error;
173

            
174
130940
    fn try_from(value: CollectionHeader<PrimaryKey>) -> Result<Self, Self::Error> {
175
130940
        Ok(Self {
176
130940
            id: DocumentId::new(&value.id)?,
177
130940
            revision: value.revision,
178
        })
179
130940
    }
180
}
181

            
182
impl<'a, PrimaryKey> TryFrom<&'a CollectionHeader<PrimaryKey>> for Header
183
where
184
    PrimaryKey: for<'k> Key<'k>,
185
{
186
    type Error = crate::Error;
187

            
188
    fn try_from(value: &'a CollectionHeader<PrimaryKey>) -> Result<Self, Self::Error> {
189
        Ok(Self {
190
            id: DocumentId::new(&value.id)?,
191
            revision: value.revision,
192
        })
193
    }
194
}
195

            
196
/// A header with either a serialized or deserialized primary key.
197
#[derive(Debug, Clone, PartialEq, Eq)]
198
pub enum AnyHeader<PrimaryKey> {
199
    /// A serialized header.
200
    Serialized(Header),
201
    /// A deserialized header.
202
    Collection(CollectionHeader<PrimaryKey>),
203
}
204

            
205
impl<PrimaryKey> AnyHeader<PrimaryKey>
206
where
207
    PrimaryKey: for<'k> Key<'k>,
208
{
209
    /// Returns the contained header as a [`Header`].
210
43932
    pub fn into_header(self) -> Result<Header, crate::Error> {
211
43932
        match self {
212
43932
            AnyHeader::Serialized(header) => Ok(header),
213
            AnyHeader::Collection(header) => Header::try_from(header),
214
        }
215
43932
    }
216
}
217

            
218
1
#[test]
219
1
fn emissions_tests() -> Result<(), crate::Error> {
220
    use crate::schema::Map;
221
    use crate::test_util::Basic;
222

            
223
1
    let doc = BorrowedDocument::with_contents::<Basic, _>(&1, &Basic::default())?;
224

            
225
1
    assert_eq!(
226
1
        doc.header.emit()?,
227
1
        Mappings::Simple(Some(Map::new(doc.header.clone(), (), ())))
228
    );
229

            
230
1
    assert_eq!(
231
1
        doc.header.emit_key(1)?,
232
1
        Mappings::Simple(Some(Map::new(doc.header.clone(), 1, ())))
233
    );
234

            
235
1
    assert_eq!(
236
1
        doc.header.emit_value(1)?,
237
1
        Mappings::Simple(Some(Map::new(doc.header.clone(), (), 1)))
238
    );
239

            
240
1
    assert_eq!(
241
1
        doc.header.emit_key_and_value(1, 2)?,
242
1
        Mappings::Simple(Some(Map::new(doc.header, 1, 2)))
243
    );
244

            
245
1
    Ok(())
246
1
}
247

            
248
1
#[test]
249
1
fn chained_mappings_test() -> Result<(), crate::Error> {
250
    use crate::schema::Map;
251
    use crate::test_util::Basic;
252

            
253
1
    let doc = BorrowedDocument::with_contents::<Basic, _>(&1, &Basic::default())?;
254

            
255
1
    assert_eq!(
256
1
        doc.header.emit()?.and(doc.header.emit()?),
257
1
        Mappings::List(vec![
258
1
            Map::new(doc.header.clone(), (), ()),
259
1
            Map::new(doc.header, (), ())
260
1
        ])
261
    );
262

            
263
1
    Ok(())
264
1
}
265

            
266
1
#[test]
267
1
fn header_display_test() {
268
1
    let original_contents = b"one";
269
1
    let revision = Revision::new(original_contents);
270
1
    let header = Header {
271
1
        id: DocumentId::new(&42_u64).unwrap(),
272
1
        revision,
273
1
    };
274
1
    assert_eq!(
275
1
        header.to_string(),
276
1
        "7$2a@0-7692c3ad3540bb803c020b3aee66cd8887123234ea0c6e7143c0add73ff431ed"
277
1
    );
278
1
}