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::context::ReadContext;
19use crate::context::WriteContext;
20use crate::error::Error;
21use crate::resolver::TypeResolver;
22use crate::resolver::{RefFlag, RefMode};
23use crate::serializer::{ForyDefault, Serializer};
24use crate::type_id::TypeId;
25use std::rc::Rc;
26
27impl<T: Serializer + ForyDefault> Serializer for Option<T> {
28    #[inline(always)]
29    fn fory_write(
30        &self,
31        context: &mut WriteContext,
32        ref_mode: RefMode,
33        write_type_info: bool,
34        has_generics: bool,
35    ) -> Result<(), Error> {
36        match ref_mode {
37            RefMode::None => {
38                // Write inner directly, no null check
39                if let Some(v) = self {
40                    T::fory_write(v, context, RefMode::None, write_type_info, has_generics)
41                } else {
42                    // None with RefMode::None is a protocol error
43                    Err(Error::invalid_data("Option::None with RefMode::None"))
44                }
45            }
46            RefMode::NullOnly => {
47                if let Some(v) = self {
48                    context.writer.write_i8(RefFlag::NotNullValue as i8);
49                    T::fory_write(v, context, RefMode::None, write_type_info, has_generics)
50                } else {
51                    context.writer.write_i8(RefFlag::Null as i8);
52                    Ok(())
53                }
54            }
55            RefMode::Tracking => {
56                // Only handle null here, pass Tracking to inner for ref handling
57                if let Some(v) = self {
58                    // DON'T write flag here - inner (e.g. Rc) handles RefValue/Ref flags
59                    T::fory_write(v, context, RefMode::Tracking, write_type_info, has_generics)
60                } else {
61                    context.writer.write_i8(RefFlag::Null as i8);
62                    Ok(())
63                }
64            }
65        }
66    }
67
68    #[inline(always)]
69    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
70        if let Some(v) = self {
71            T::fory_write_data(v, context)
72        } else {
73            unreachable!("write should be call by serialize")
74        }
75    }
76
77    #[inline(always)]
78    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
79        T::fory_write_type_info(context)
80    }
81
82    fn fory_read(
83        context: &mut ReadContext,
84        ref_mode: RefMode,
85        read_type_info: bool,
86    ) -> Result<Self, Error>
87    where
88        Self: Sized + ForyDefault,
89    {
90        match ref_mode {
91            RefMode::None => {
92                // Read inner directly, no null check
93                Ok(Some(T::fory_read(context, RefMode::None, read_type_info)?))
94            }
95            RefMode::NullOnly => {
96                let ref_flag = context.reader.read_i8()?;
97                if ref_flag == RefFlag::Null as i8 {
98                    return Ok(None);
99                }
100                // NotNullValue - read inner without ref handling
101                Ok(Some(T::fory_read(context, RefMode::None, read_type_info)?))
102            }
103            RefMode::Tracking => {
104                let ref_flag = context.reader.read_i8()?;
105                if ref_flag == RefFlag::Null as i8 {
106                    return Ok(None);
107                }
108                // Rewind to let inner type handle the ref flag (RefValue/Ref)
109                context.reader.move_back(1);
110                Ok(Some(T::fory_read(
111                    context,
112                    RefMode::Tracking,
113                    read_type_info,
114                )?))
115            }
116        }
117    }
118
119    fn fory_read_with_type_info(
120        context: &mut ReadContext,
121        ref_mode: RefMode,
122        type_info: Rc<crate::TypeInfo>,
123    ) -> Result<Self, Error>
124    where
125        Self: Sized + ForyDefault,
126    {
127        match ref_mode {
128            RefMode::None => {
129                if T::fory_is_polymorphic() {
130                    Ok(Some(T::fory_read_with_type_info(
131                        context,
132                        RefMode::None,
133                        type_info,
134                    )?))
135                } else {
136                    Ok(Some(T::fory_read_data(context)?))
137                }
138            }
139            RefMode::NullOnly => {
140                let ref_flag = context.reader.read_i8()?;
141                if ref_flag == RefFlag::Null as i8 {
142                    return Ok(None);
143                }
144                if T::fory_is_polymorphic() {
145                    Ok(Some(T::fory_read_with_type_info(
146                        context,
147                        RefMode::None,
148                        type_info,
149                    )?))
150                } else {
151                    Ok(Some(T::fory_read_data(context)?))
152                }
153            }
154            RefMode::Tracking => {
155                let ref_flag = context.reader.read_i8()?;
156                if ref_flag == RefFlag::Null as i8 {
157                    return Ok(None);
158                }
159                // Rewind to let inner type handle the ref flag
160                context.reader.move_back(1);
161                Ok(Some(T::fory_read_with_type_info(
162                    context,
163                    RefMode::Tracking,
164                    type_info,
165                )?))
166            }
167        }
168    }
169
170    #[inline(always)]
171    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
172        if T::fory_is_polymorphic() {
173            Ok(Some(T::fory_read(context, RefMode::None, true)?))
174        } else {
175            Ok(Some(T::fory_read_data(context)?))
176        }
177    }
178
179    #[inline(always)]
180    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
181        T::fory_read_type_info(context)
182    }
183
184    #[inline(always)]
185    fn fory_reserved_space() -> usize {
186        std::mem::size_of::<T>()
187    }
188
189    #[inline(always)]
190    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
191        T::fory_get_type_id(type_resolver)
192    }
193
194    #[inline(always)]
195    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
196        match self {
197            Some(val) => val.fory_type_id_dyn(type_resolver),
198            None => T::fory_get_type_id(type_resolver),
199        }
200    }
201
202    #[inline(always)]
203    fn fory_is_option() -> bool {
204        true
205    }
206
207    #[inline(always)]
208    fn fory_is_none(&self) -> bool {
209        self.is_none()
210    }
211
212    #[inline(always)]
213    fn fory_static_type_id() -> TypeId {
214        T::fory_static_type_id()
215    }
216
217    fn fory_is_wrapper_type() -> bool
218    where
219        Self: Sized,
220    {
221        true
222    }
223
224    #[inline(always)]
225    fn as_any(&self) -> &dyn std::any::Any {
226        self
227    }
228}
229
230impl<T: ForyDefault> ForyDefault for Option<T> {
231    #[inline(always)]
232    fn fory_default() -> Self {
233        None
234    }
235}