matrix_sdk_indexeddb/media_store/serializer/foreign.rs
1// Copyright 2025 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License
14
15pub mod ignore_media_retention_policy {
16 //! This module contains a foreign implementation of [`serde::Serialize`]
17 //! and [`serde::Deserialize`] for [`IgnoreMediaRetentionPolicy`]. These
18 //! implementations can be injected with the proper macros, i.e.,
19 //! `#[serde(with = "path::to::this::module")]`.
20 //!
21 //! This is necessary, as [`IgnoreMediaRetentionPolicy`] does not implement
22 //! these traits directly.
23
24 use matrix_sdk_base::media::store::IgnoreMediaRetentionPolicy;
25 use serde::{Deserializer, Serializer};
26
27 /// Serializes an [`IgnoreMediaRetentionPolicy`] as a `u8`, where
28 /// [`IgnoreMediaRetentionPolicy::No`] is `0`
29 /// and [`IgnoreMediaRetentionPolicy::Yes`] is `1`.
30 ///
31 /// Note that this is not serialized as a `bool` because boolean values are
32 /// not supported as IndexedDB keys.
33 pub fn serialize<S>(ignore_policy: &IgnoreMediaRetentionPolicy, s: S) -> Result<S::Ok, S::Error>
34 where
35 S: Serializer,
36 {
37 s.serialize_u8(match ignore_policy {
38 IgnoreMediaRetentionPolicy::Yes => 1,
39 IgnoreMediaRetentionPolicy::No => 0,
40 })
41 }
42
43 /// Deserializes a `u8` into an [`IgnoreMediaRetentionPolicy`] where `0` is
44 /// [`IgnoreMediaRetentionPolicy::No`] and anything else is
45 /// [`IgnoreMediaRetentionPolicy::Yes`].
46 pub fn deserialize<'de, D>(d: D) -> Result<IgnoreMediaRetentionPolicy, D::Error>
47 where
48 D: Deserializer<'de>,
49 {
50 Ok(match serde::de::Deserialize::deserialize(d)? {
51 0u8 => IgnoreMediaRetentionPolicy::No,
52 _ => IgnoreMediaRetentionPolicy::Yes,
53 })
54 }
55}
56
57pub mod unix_time {
58 //! This module contains an alternative implementation of
59 //! [`serde::Serialize`] and [`serde::Deserialize`] for [`UnixTime`].
60 //! These implementations can be injected with the proper macros, i.e.,
61 //! `#[serde(with = "path::to::this::module")]`.
62 //!
63 //! This is necessary, as the derived implementation of [`UnixTime`] does
64 //! not produce values which can be used in IndexedDB keys.
65
66 use std::time::Duration;
67
68 use serde::{Deserializer, Serializer};
69
70 use crate::media_store::types::UnixTime;
71
72 /// Serializes a [`UnixTime`] as an `i64` which represents an amount of
73 /// seconds relative to the [`UNIX_EPOCH`](ruma::time::UNIX_EPOCH).
74 /// [`UnixTime::BeforeEpoch`] is represented as a negative value
75 /// and [`UnixTime::AfterEpoch`] is represented as a positive value.
76 pub fn serialize<S>(unix_time: &UnixTime, s: S) -> Result<S::Ok, S::Error>
77 where
78 S: Serializer,
79 {
80 s.serialize_i64(match unix_time {
81 UnixTime::BeforeEpoch(duration) => {
82 -i64::try_from(duration.as_secs()).map_err(serde::ser::Error::custom)?
83 }
84 UnixTime::AfterEpoch(duration) => {
85 i64::try_from(duration.as_secs()).map_err(serde::ser::Error::custom)?
86 }
87 })
88 }
89
90 /// Deserializes an `i64` into a [`UnixTime`]. Negative values represent
91 /// the number of seconds before the [`UNIX_EPOCH`][1] and are deserialized
92 /// into [`UnixTime::BeforeEpoch`]. Positive values represent
93 /// the number of seconds after the [`UNIX_EPOCH`][1] and are deserialized
94 /// into [`UnixTime::AfterEpoch`].
95 ///
96 /// [1]: ruma::time::UNIX_EPOCH
97 pub fn deserialize<'de, D>(d: D) -> Result<UnixTime, D::Error>
98 where
99 D: Deserializer<'de>,
100 {
101 let seconds: i64 = serde::de::Deserialize::deserialize(d)?;
102 Ok(match seconds {
103 seconds @ ..0 => UnixTime::BeforeEpoch(Duration::from_secs(seconds.unsigned_abs())),
104 seconds @ 0.. => UnixTime::AfterEpoch(Duration::from_secs(seconds.unsigned_abs())),
105 })
106 }
107}