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
use ;
use crateInvalidBinary;
/// A diesel serialization and deserialization wrapper for a fixed-length
/// PostgreSQL [`bytea`](diesel::sql_types::Binary) column.
///
/// Wraps an `[u8; N]` and checks, at runtime, that the stored/loaded blob is
/// exactly `N` bytes long. This makes it possible to model a `bytea` column
/// whose length is known at compile time, instead of relying on a loosely-typed
/// `Vec<u8>`.
///
/// To be completely safe, you should also add the following `CHECK` constraint:
/// ```sql
/// length(bytea_field) = N
/// ```
///
/// This type is not intended to be used directly in the model but rather to be
/// used with diesel [`serialize_as`] and [`deserialize_as`].
///
/// ```
/// use benzina::{Binary, U63};
/// use diesel::{Insertable, Queryable};
///
/// #[derive(Debug, Queryable)]
/// #[diesel(table_name = objects, check_for_backend(diesel::pg::Pg))]
/// struct Object {
/// id: U63,
/// // A SHA-256 digest of the object's content (always 32 bytes)
/// #[diesel(deserialize_as = Binary<32>)]
/// content_sha256: ObjectDigest,
/// }
///
/// #[derive(Debug, Insertable)]
/// #[diesel(table_name = objects)]
/// struct NewObject {
/// // A SHA-256 digest of the object's content (always 32 bytes)
/// #[diesel(serialize_as = Binary<32>)]
/// content_sha256: ObjectDigest,
/// }
///
/// /// A SHA-256 content digest (always 32 bytes).
/// #[derive(Debug)]
/// struct ObjectDigest([u8; 32]);
///
/// // needed by deserialize_as
/// impl From<benzina::Binary<32>> for ObjectDigest {
/// fn from(value: benzina::Binary<32>) -> Self {
/// Self(value.into_inner())
/// }
/// }
///
/// // needed by serialize_as
/// impl From<ObjectDigest> for benzina::Binary<32> {
/// fn from(value: ObjectDigest) -> Self {
/// benzina::Binary::new(value.0)
/// }
/// }
///
/// diesel::table! {
/// objects (id) {
/// id -> Int8,
/// content_sha256 -> Bytea,
/// }
/// }
/// ```
///
/// [`serialize_as`]: diesel::prelude::Insertable#optional-field-attributes
/// [`deserialize_as`]: diesel::prelude::Queryable#deserialize_as-attribute
;