Skip to main content

fory_core/serializer/
struct_.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, WriteContext};
19use crate::ensure;
20use crate::error::Error;
21use crate::serializer::StructSerializer;
22use crate::type_id::TypeId;
23use crate::util::ENABLE_FORY_DEBUG_OUTPUT;
24use std::any::Any;
25
26#[inline(always)]
27pub fn actual_type_id(_type_id: u32, register_by_name: bool, compatible: bool) -> u32 {
28    if compatible {
29        if register_by_name {
30            TypeId::NAMED_COMPATIBLE_STRUCT as u32
31        } else {
32            TypeId::COMPATIBLE_STRUCT as u32
33        }
34    } else if register_by_name {
35        TypeId::NAMED_STRUCT as u32
36    } else {
37        TypeId::STRUCT as u32
38    }
39}
40
41#[inline(always)]
42pub fn write_type_info_fast<T: StructSerializer>(context: &mut WriteContext) -> Result<(), Error> {
43    context.write_struct_type_info::<T>()
44}
45
46#[inline(always)]
47pub fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
48    context.read_any_type_info()?;
49    Ok(())
50}
51
52#[inline(always)]
53pub fn read_type_info_fast<T: StructSerializer>(context: &mut ReadContext) -> Result<(), Error> {
54    if context.is_compatible() || context.is_xlang() {
55        return read_type_info(context);
56    }
57    let local_type_id = context
58        .get_type_resolver()
59        .get_type_id_by_index(T::type_index())?;
60    let local_type_id_u32 = local_type_id as u32;
61    if !crate::type_id::needs_user_type_id(local_type_id_u32) {
62        return read_type_info(context);
63    }
64    let remote_type_id = context.reader.read_u8()? as u32;
65    ensure!(
66        local_type_id_u32 == remote_type_id,
67        Error::type_mismatch(local_type_id_u32, remote_type_id)
68    );
69    let remote_user_type_id = context.reader.read_var_u32()?;
70    let local_user_type_id = context
71        .get_type_resolver()
72        .get_user_type_id_by_index(&std::any::TypeId::of::<T>(), T::type_index())?;
73    if remote_user_type_id != local_user_type_id {
74        return Err(Error::type_error(format!(
75            "User type id mismatch: local {} vs remote {}",
76            local_user_type_id, remote_user_type_id
77        )));
78    }
79    Ok(())
80}
81
82#[doc(hidden)]
83#[cold]
84#[inline(never)]
85pub fn invalid_ref_flag(ref_flag: i8) -> Error {
86    Error::invalid_ref(format!("Unknown ref flag, value:{ref_flag}"))
87}
88
89pub type BeforeWriteFieldFunc =
90    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut WriteContext);
91pub type AfterWriteFieldFunc =
92    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut WriteContext);
93pub type BeforeReadFieldFunc = fn(struct_name: &str, field_name: &str, context: &mut ReadContext);
94pub type AfterReadFieldFunc =
95    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut ReadContext);
96
97fn default_before_write_field(
98    struct_name: &str,
99    field_name: &str,
100    _field_value: &dyn Any,
101    context: &mut WriteContext,
102) {
103    if ENABLE_FORY_DEBUG_OUTPUT {
104        println!(
105            "before_write_field:\tstruct={struct_name},\tfield={field_name},\twriter_len={}",
106            context.writer.len()
107        );
108    }
109}
110
111fn default_after_write_field(
112    struct_name: &str,
113    field_name: &str,
114    _field_value: &dyn Any,
115    context: &mut WriteContext,
116) {
117    if ENABLE_FORY_DEBUG_OUTPUT {
118        println!(
119            "after_write_field:\tstruct={struct_name},\tfield={field_name},\twriter_len={}",
120            context.writer.len()
121        );
122    }
123}
124
125fn default_before_read_field(struct_name: &str, field_name: &str, context: &mut ReadContext) {
126    if ENABLE_FORY_DEBUG_OUTPUT {
127        println!(
128            "before_read_field:\tstruct={struct_name},\tfield={field_name},\treader_cursor={}",
129            context.reader.get_cursor()
130        );
131    }
132}
133
134fn default_after_read_field(
135    struct_name: &str,
136    field_name: &str,
137    _field_value: &dyn Any,
138    context: &mut ReadContext,
139) {
140    if ENABLE_FORY_DEBUG_OUTPUT {
141        println!(
142            "after_read_field:\tstruct={struct_name},\tfield={field_name},\treader_cursor={}",
143            context.reader.get_cursor()
144        );
145    }
146}
147
148static mut BEFORE_WRITE_FIELD_FUNC: BeforeWriteFieldFunc = default_before_write_field;
149static mut AFTER_WRITE_FIELD_FUNC: AfterWriteFieldFunc = default_after_write_field;
150static mut BEFORE_READ_FIELD_FUNC: BeforeReadFieldFunc = default_before_read_field;
151static mut AFTER_READ_FIELD_FUNC: AfterReadFieldFunc = default_after_read_field;
152
153pub fn set_before_write_field_func(func: BeforeWriteFieldFunc) {
154    unsafe { BEFORE_WRITE_FIELD_FUNC = func }
155}
156
157pub fn set_after_write_field_func(func: AfterWriteFieldFunc) {
158    unsafe { AFTER_WRITE_FIELD_FUNC = func }
159}
160
161pub fn set_before_read_field_func(func: BeforeReadFieldFunc) {
162    unsafe { BEFORE_READ_FIELD_FUNC = func }
163}
164
165pub fn set_after_read_field_func(func: AfterReadFieldFunc) {
166    unsafe { AFTER_READ_FIELD_FUNC = func }
167}
168
169pub fn reset_struct_debug_hooks() {
170    unsafe {
171        BEFORE_WRITE_FIELD_FUNC = default_before_write_field;
172        AFTER_WRITE_FIELD_FUNC = default_after_write_field;
173        BEFORE_READ_FIELD_FUNC = default_before_read_field;
174        AFTER_READ_FIELD_FUNC = default_after_read_field;
175    }
176}
177
178/// Debug method to hook into struct serialization
179pub fn struct_before_write_field(
180    struct_name: &str,
181    field_name: &str,
182    field_value: &dyn Any,
183    context: &mut WriteContext,
184) {
185    unsafe { BEFORE_WRITE_FIELD_FUNC(struct_name, field_name, field_value, context) }
186}
187
188/// Debug method to hook into struct serialization
189pub fn struct_after_write_field(
190    struct_name: &str,
191    field_name: &str,
192    field_value: &dyn Any,
193    context: &mut WriteContext,
194) {
195    unsafe { AFTER_WRITE_FIELD_FUNC(struct_name, field_name, field_value, context) }
196}
197
198/// Debug method to hook into struct deserialization
199pub fn struct_before_read_field(struct_name: &str, field_name: &str, context: &mut ReadContext) {
200    unsafe { BEFORE_READ_FIELD_FUNC(struct_name, field_name, context) }
201}
202
203/// Debug method to hook into struct deserialization
204pub fn struct_after_read_field(
205    struct_name: &str,
206    field_name: &str,
207    field_value: &dyn Any,
208    context: &mut ReadContext,
209) {
210    unsafe { AFTER_READ_FIELD_FUNC(struct_name, field_name, field_value, context) }
211}