Skip to main content

fory_core/serializer/
option.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::error::Error;
19use crate::resolver::context::ReadContext;
20use crate::resolver::context::WriteContext;
21use crate::resolver::type_resolver::TypeResolver;
22use crate::serializer::{ForyDefault, Serializer};
23use crate::types::{RefFlag, RefMode, TypeId};
24use std::rc::Rc;
25
26impl<T: Serializer + ForyDefault> Serializer for Option<T> {
27    #[inline(always)]
28    fn fory_write(
29        &self,
30        context: &mut WriteContext,
31        ref_mode: RefMode,
32        write_type_info: bool,
33        has_generics: bool,
34    ) -> Result<(), Error> {
35        match ref_mode {
36            RefMode::None => {
37                // Write inner directly, no null check
38                if let Some(v) = self {
39                    T::fory_write(v, context, RefMode::None, write_type_info, has_generics)
40                } else {
41                    // None with RefMode::None is a protocol error
42                    Err(Error::invalid_data("Option::None with RefMode::None"))
43                }
44            }
45            RefMode::NullOnly => {
46                if let Some(v) = self {
47                    context.writer.write_i8(RefFlag::NotNullValue as i8);
48                    T::fory_write(v, context, RefMode::None, write_type_info, has_generics)
49                } else {
50                    context.writer.write_i8(RefFlag::Null as i8);
51                    Ok(())
52                }
53            }
54            RefMode::Tracking => {
55                // Only handle null here, pass Tracking to inner for ref handling
56                if let Some(v) = self {
57                    // DON'T write flag here - inner (e.g. Rc) handles RefValue/Ref flags
58                    T::fory_write(v, context, RefMode::Tracking, write_type_info, has_generics)
59                } else {
60                    context.writer.write_i8(RefFlag::Null as i8);
61                    Ok(())
62                }
63            }
64        }
65    }
66
67    #[inline(always)]
68    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
69        if let Some(v) = self {
70            T::fory_write_data(v, context)
71        } else {
72            unreachable!("write should be call by serialize")
73        }
74    }
75
76    #[inline(always)]
77    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
78        T::fory_write_type_info(context)
79    }
80
81    fn fory_read(
82        context: &mut ReadContext,
83        ref_mode: RefMode,
84        read_type_info: bool,
85    ) -> Result<Self, Error>
86    where
87        Self: Sized + ForyDefault,
88    {
89        match ref_mode {
90            RefMode::None => {
91                // Read inner directly, no null check
92                Ok(Some(T::fory_read(context, RefMode::None, read_type_info)?))
93            }
94            RefMode::NullOnly => {
95                let ref_flag = context.reader.read_i8()?;
96                if ref_flag == RefFlag::Null as i8 {
97                    return Ok(None);
98                }
99                // NotNullValue - read inner without ref handling
100                Ok(Some(T::fory_read(context, RefMode::None, read_type_info)?))
101            }
102            RefMode::Tracking => {
103                let ref_flag = context.reader.read_i8()?;
104                if ref_flag == RefFlag::Null as i8 {
105                    return Ok(None);
106                }
107                // Rewind to let inner type handle the ref flag (RefValue/Ref)
108                context.reader.move_back(1);
109                Ok(Some(T::fory_read(
110                    context,
111                    RefMode::Tracking,
112                    read_type_info,
113                )?))
114            }
115        }
116    }
117
118    fn fory_read_with_type_info(
119        context: &mut ReadContext,
120        ref_mode: RefMode,
121        type_info: Rc<crate::TypeInfo>,
122    ) -> Result<Self, Error>
123    where
124        Self: Sized + ForyDefault,
125    {
126        match ref_mode {
127            RefMode::None => {
128                if T::fory_is_polymorphic() {
129                    Ok(Some(T::fory_read_with_type_info(
130                        context,
131                        RefMode::None,
132                        type_info,
133                    )?))
134                } else {
135                    Ok(Some(T::fory_read_data(context)?))
136                }
137            }
138            RefMode::NullOnly => {
139                let ref_flag = context.reader.read_i8()?;
140                if ref_flag == RefFlag::Null as i8 {
141                    return Ok(None);
142                }
143                if T::fory_is_polymorphic() {
144                    Ok(Some(T::fory_read_with_type_info(
145                        context,
146                        RefMode::None,
147                        type_info,
148                    )?))
149                } else {
150                    Ok(Some(T::fory_read_data(context)?))
151                }
152            }
153            RefMode::Tracking => {
154                let ref_flag = context.reader.read_i8()?;
155                if ref_flag == RefFlag::Null as i8 {
156                    return Ok(None);
157                }
158                // Rewind to let inner type handle the ref flag
159                context.reader.move_back(1);
160                Ok(Some(T::fory_read_with_type_info(
161                    context,
162                    RefMode::Tracking,
163                    type_info,
164                )?))
165            }
166        }
167    }
168
169    #[inline(always)]
170    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
171        if T::fory_is_polymorphic() {
172            Ok(Some(T::fory_read(context, RefMode::None, true)?))
173        } else {
174            Ok(Some(T::fory_read_data(context)?))
175        }
176    }
177
178    #[inline(always)]
179    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
180        T::fory_read_type_info(context)
181    }
182
183    #[inline(always)]
184    fn fory_reserved_space() -> usize {
185        std::mem::size_of::<T>()
186    }
187
188    #[inline(always)]
189    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
190        T::fory_get_type_id(type_resolver)
191    }
192
193    #[inline(always)]
194    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
195        match self {
196            Some(val) => val.fory_type_id_dyn(type_resolver),
197            None => T::fory_get_type_id(type_resolver),
198        }
199    }
200
201    #[inline(always)]
202    fn fory_is_option() -> bool {
203        true
204    }
205
206    #[inline(always)]
207    fn fory_is_none(&self) -> bool {
208        self.is_none()
209    }
210
211    #[inline(always)]
212    fn fory_static_type_id() -> TypeId {
213        T::fory_static_type_id()
214    }
215
216    fn fory_is_wrapper_type() -> bool
217    where
218        Self: Sized,
219    {
220        true
221    }
222
223    #[inline(always)]
224    fn as_any(&self) -> &dyn std::any::Any {
225        self
226    }
227}
228
229impl<T: ForyDefault> ForyDefault for Option<T> {
230    #[inline(always)]
231    fn fory_default() -> Self {
232        None
233    }
234}