sea_orm/entity/compound/
has_one.rs1use crate::{ActiveHasOne, EntityTrait};
2
3#[derive_where::derive_where(Debug, Clone, PartialEq, Eq, Hash; E::ModelEx)]
4#[derive(Default)]
5pub enum HasOne<E>
6where
7 E: EntityTrait,
8{
9 #[default]
10 Unloaded,
11 Loaded(Option<Box<E::ModelEx>>),
12}
13
14impl<E> HasOne<E>
15where
16 E: EntityTrait,
17{
18 pub fn loaded(model: Option<impl Into<E::ModelEx>>) -> Self {
19 Self::Loaded(model.map(|model| Box::new(model.into())))
20 }
21
22 pub fn is_unloaded(&self) -> bool {
24 matches!(self, Self::Unloaded)
25 }
26
27 pub fn is_loaded(&self) -> bool {
29 matches!(self, Self::Loaded(_))
30 }
31
32 pub fn is_not_found(&self) -> bool {
34 matches!(self, Self::Loaded(None))
35 }
36
37 pub fn is_none(&self) -> bool {
39 matches!(self, Self::Unloaded | Self::Loaded(None))
40 }
41
42 pub fn as_ref(&self) -> Option<&E::ModelEx> {
44 match self {
45 Self::Loaded(Some(model)) => Some(model.as_ref()),
46 Self::Unloaded | Self::Loaded(None) => None,
47 }
48 }
49
50 pub fn as_mut(&mut self) -> Option<&mut E::ModelEx> {
52 match self {
53 Self::Loaded(Some(model)) => Some(model),
54 Self::Unloaded | Self::Loaded(None) => None,
55 }
56 }
57
58 pub fn into_option(self) -> Option<E::ModelEx> {
60 match self {
61 Self::Loaded(Some(model)) => Some(*model),
62 Self::Unloaded | Self::Loaded(None) => None,
63 }
64 }
65
66 pub fn take(&mut self) -> Option<E::ModelEx> {
68 std::mem::take(self).into_option()
69 }
70
71 pub fn unwrap(self) -> E::ModelEx {
75 match self {
76 Self::Loaded(Some(model)) => *model,
77 Self::Unloaded => panic!("called `HasOne::unwrap()` on an `Unloaded` value"),
78 Self::Loaded(None) => panic!("called `HasOne::unwrap()` on a `Loaded(None)` value"),
79 }
80 }
81}
82
83impl<E> HasOne<E>
84where
85 E: EntityTrait,
86 E::ActiveModelEx: From<E::ModelEx>,
87{
88 pub fn into_active_model(self) -> ActiveHasOne<E> {
89 match self {
90 Self::Loaded(Some(model)) => ActiveHasOne::set(Some(*model)),
91 Self::Unloaded | Self::Loaded(None) => ActiveHasOne::NotSet,
92 }
93 }
94}
95
96impl<E: EntityTrait> From<HasOne<E>> for Option<Box<E::ModelEx>> {
97 fn from(value: HasOne<E>) -> Self {
98 match value {
99 HasOne::Loaded(model) => model,
100 HasOne::Unloaded => None,
101 }
102 }
103}
104
105impl<E: EntityTrait> From<Option<Box<E::ModelEx>>> for HasOne<E> {
106 fn from(value: Option<Box<E::ModelEx>>) -> Self {
107 Self::Loaded(value)
108 }
109}
110
111#[cfg(feature = "with-json")]
112impl<E> serde::Serialize for HasOne<E>
113where
114 E: EntityTrait,
115 E::ModelEx: serde::Serialize,
116{
117 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: serde::Serializer,
120 {
121 match self {
122 HasOne::Unloaded => None,
123 HasOne::Loaded(model) => model.as_ref(),
124 }
125 .serialize(serializer)
126 }
127}
128
129#[cfg(feature = "with-json")]
130impl<'de, E> serde::Deserialize<'de> for HasOne<E>
131where
132 E: EntityTrait,
133 E::ModelEx: serde::Deserialize<'de>,
134{
135 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136 where
137 D: serde::Deserializer<'de>,
138 {
139 match <Option<E::ModelEx>>::deserialize(deserializer)? {
140 Some(model) => Ok(HasOne::Loaded(Some(Box::new(model)))),
141 None => Ok(HasOne::Unloaded),
142 }
143 }
144}