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::ensure;
19use crate::error::Error;
20use crate::resolver::context::{ReadContext, WriteContext};
21use crate::serializer::Serializer;
22use crate::types::{RefFlag, 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            (type_id << 8) + TypeId::COMPATIBLE_STRUCT as u32
33        }
34    } else if register_by_name {
35        TypeId::NAMED_STRUCT as u32
36    } else {
37        (type_id << 8) + TypeId::STRUCT as u32
38    }
39}
40
41#[inline(always)]
42pub fn write_type_info<T: Serializer>(context: &mut WriteContext) -> Result<(), Error> {
43    let type_id = T::fory_get_type_id(context.get_type_resolver())?;
44    context.writer.write_varuint32(type_id);
45    let rs_type_id = std::any::TypeId::of::<T>();
46
47    if type_id & 0xff == TypeId::NAMED_STRUCT as u32 {
48        if context.is_share_meta() {
49            let meta_index = context.push_meta(rs_type_id)? as u32;
50            context.writer.write_varuint32(meta_index);
51        } else {
52            let type_info = context.get_type_resolver().get_type_info(&rs_type_id)?;
53            let namespace = type_info.get_namespace();
54            let type_name = type_info.get_type_name();
55            context.write_meta_string_bytes(namespace)?;
56            context.write_meta_string_bytes(type_name)?;
57        }
58    } else if type_id & 0xff == TypeId::NAMED_COMPATIBLE_STRUCT as u32
59        || type_id & 0xff == TypeId::COMPATIBLE_STRUCT as u32
60    {
61        let meta_index = context.push_meta(rs_type_id)? as u32;
62        context.writer.write_varuint32(meta_index);
63    }
64    Ok(())
65}
66
67#[inline(always)]
68pub fn read_type_info<T: Serializer>(context: &mut ReadContext) -> Result<(), Error> {
69    let remote_type_id = context.reader.read_varuint32()?;
70    let local_type_id = T::fory_get_type_id(context.get_type_resolver())?;
71    ensure!(
72        local_type_id == remote_type_id,
73        Error::type_mismatch(local_type_id, remote_type_id)
74    );
75
76    if local_type_id & 0xff == TypeId::NAMED_STRUCT as u32 {
77        if context.is_share_meta() {
78            let _meta_index = context.reader.read_varuint32()?;
79        } else {
80            let _namespace_msb = context.read_meta_string()?;
81            let _type_name_msb = context.read_meta_string()?;
82        }
83    } else if local_type_id & 0xff == TypeId::NAMED_COMPATIBLE_STRUCT as u32
84        || local_type_id & 0xff == TypeId::COMPATIBLE_STRUCT as u32
85    {
86        let _meta_index = context.reader.read_varuint32();
87    }
88    Ok(())
89}
90
91#[inline(always)]
92pub fn write<T: Serializer>(
93    this: &T,
94    context: &mut WriteContext,
95    write_ref_info: bool,
96    write_type_info: bool,
97) -> Result<(), Error> {
98    if write_ref_info {
99        context.writer.write_i8(RefFlag::NotNullValue as i8);
100    }
101    if write_type_info {
102        T::fory_write_type_info(context)?;
103    }
104    this.fory_write_data(context)
105}
106
107pub type BeforeWriteFieldFunc =
108    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut WriteContext);
109pub type AfterWriteFieldFunc =
110    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut WriteContext);
111pub type BeforeReadFieldFunc = fn(struct_name: &str, field_name: &str, context: &mut ReadContext);
112pub type AfterReadFieldFunc =
113    fn(struct_name: &str, field_name: &str, field_value: &dyn Any, context: &mut ReadContext);
114
115fn default_before_write_field(
116    struct_name: &str,
117    field_name: &str,
118    _field_value: &dyn Any,
119    context: &mut WriteContext,
120) {
121    if ENABLE_FORY_DEBUG_OUTPUT {
122        println!(
123            "before_write_field:\tstruct={struct_name},\tfield={field_name},\twriter_len={}",
124            context.writer.len()
125        );
126    }
127}
128
129fn default_after_write_field(
130    struct_name: &str,
131    field_name: &str,
132    _field_value: &dyn Any,
133    context: &mut WriteContext,
134) {
135    if ENABLE_FORY_DEBUG_OUTPUT {
136        println!(
137            "after_write_field:\tstruct={struct_name},\tfield={field_name},\twriter_len={}",
138            context.writer.len()
139        );
140    }
141}
142
143fn default_before_read_field(struct_name: &str, field_name: &str, context: &mut ReadContext) {
144    if ENABLE_FORY_DEBUG_OUTPUT {
145        println!(
146            "before_read_field:\tstruct={struct_name},\tfield={field_name},\treader_cursor={}",
147            context.reader.get_cursor()
148        );
149    }
150}
151
152fn default_after_read_field(
153    struct_name: &str,
154    field_name: &str,
155    _field_value: &dyn Any,
156    context: &mut ReadContext,
157) {
158    if ENABLE_FORY_DEBUG_OUTPUT {
159        println!(
160            "after_read_field:\tstruct={struct_name},\tfield={field_name},\treader_cursor={}",
161            context.reader.get_cursor()
162        );
163    }
164}
165
166static mut BEFORE_WRITE_FIELD_FUNC: BeforeWriteFieldFunc = default_before_write_field;
167static mut AFTER_WRITE_FIELD_FUNC: AfterWriteFieldFunc = default_after_write_field;
168static mut BEFORE_READ_FIELD_FUNC: BeforeReadFieldFunc = default_before_read_field;
169static mut AFTER_READ_FIELD_FUNC: AfterReadFieldFunc = default_after_read_field;
170
171pub fn set_before_write_field_func(func: BeforeWriteFieldFunc) {
172    unsafe { BEFORE_WRITE_FIELD_FUNC = func }
173}
174
175pub fn set_after_write_field_func(func: AfterWriteFieldFunc) {
176    unsafe { AFTER_WRITE_FIELD_FUNC = func }
177}
178
179pub fn set_before_read_field_func(func: BeforeReadFieldFunc) {
180    unsafe { BEFORE_READ_FIELD_FUNC = func }
181}
182
183pub fn set_after_read_field_func(func: AfterReadFieldFunc) {
184    unsafe { AFTER_READ_FIELD_FUNC = func }
185}
186
187pub fn reset_struct_debug_hooks() {
188    unsafe {
189        BEFORE_WRITE_FIELD_FUNC = default_before_write_field;
190        AFTER_WRITE_FIELD_FUNC = default_after_write_field;
191        BEFORE_READ_FIELD_FUNC = default_before_read_field;
192        AFTER_READ_FIELD_FUNC = default_after_read_field;
193    }
194}
195
196/// Debug method to hook into struct serialization
197pub fn struct_before_write_field(
198    struct_name: &str,
199    field_name: &str,
200    field_value: &dyn Any,
201    context: &mut WriteContext,
202) {
203    unsafe { BEFORE_WRITE_FIELD_FUNC(struct_name, field_name, field_value, context) }
204}
205
206/// Debug method to hook into struct serialization
207pub fn struct_after_write_field(
208    struct_name: &str,
209    field_name: &str,
210    field_value: &dyn Any,
211    context: &mut WriteContext,
212) {
213    unsafe { AFTER_WRITE_FIELD_FUNC(struct_name, field_name, field_value, context) }
214}
215
216/// Debug method to hook into struct deserialization
217pub fn struct_before_read_field(struct_name: &str, field_name: &str, context: &mut ReadContext) {
218    unsafe { BEFORE_READ_FIELD_FUNC(struct_name, field_name, context) }
219}
220
221/// Debug method to hook into struct deserialization
222pub fn struct_after_read_field(
223    struct_name: &str,
224    field_name: &str,
225    field_value: &dyn Any,
226    context: &mut ReadContext,
227) {
228    unsafe { AFTER_READ_FIELD_FUNC(struct_name, field_name, field_value, context) }
229}